Имя: Пароль:
1C
 
Проблема блокировок при работе с планом обмена
, ,
0 mzelensky
 
06.04.21
12:46
Доброго времени суток!

Есть план обмен, работа с которым реализована следующим образом:


1) Получение данных из узла, присвоение выбранным данным "Номера сообщения" (для последующей очистки)

Функция ЗаполнитьСтруктуруИзмененийДляУзла_Справочники(УзелПланаОбмена, ИмяТаблицы)
    
    РезультатФункции = Новый Структура("ДанныеРегистрации, НомерИсходящегоСообщения");
    
    ОтобразитьСостояние("Выборка изменений ...");
    
    Если Метаданные.Справочники.Найти(ИмяТаблицы) <> Неопределено Тогда
        Если ЗначениеЗаполнено(УзелПланаОбмена) Тогда
            Запрос = Новый Запрос;
            Запрос.Текст ="ВЫБРАТЬ ПЕРВЫЕ 3000
            |    Изменения.Ссылка КАК Объект
            |ИЗ
            |    Справочник." + ИмяТаблицы + ".Изменения КАК Изменения
            |ГДЕ
            |    Изменения.Узел = &Узел";
            Запрос.УстановитьПараметр("Узел", УзелПланаОбмена);
            
            ДанныеРегистрации = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Объект");
            
            //
            Если ДанныеРегистрации.Количество() > 0 Тогда
                
                ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
                Запись = Новый ЗаписьXML;
                Запись.УстановитьСтроку();
                ЗаписьСообщения.НачатьЗапись(Запись, УзелПланаОбмена);
                
                ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель, ЗаписьСообщения.НомерСообщения, ДанныеРегистрации);
                
                РезультатФункции.Вставить("ДанныеРегистрации", ДанныеРегистрации);
                РезультатФункции.Вставить("НомерИсходящегоСообщения", ЗаписьСообщения.НомерСообщения);
                
                ЗаписьСообщения.ЗакончитьЗапись();
                Запись.Закрыть();
                
                ВыборкаИзменений = Неопределено;
                ЗаписьСообщения  = Неопределено;
                Запись              = Неопределено;
                
            КонецЕсли;
        
        КонецЕсли;
    КонецЕсли;
    
    Возврат РезультатФункции;
    
КонецФункции


...

2) Происходит выгрузка сведений

...

3) Удаление из плана обмена успешно выгруженных данных (и не поменявшихся за момень выгрузки)

Функция ОчиститьИзмененияДляУзла_Справочники(УзелПланаОбмена, ИмяТаблицы, НомерСообщения, ДанныеУдаляемыеИзРегистрации)
    
    РезультатФункции = Истина;
    
    ОтобразитьСостояние("Очистка изменений ...");
    
    Если Метаданные.Справочники.Найти(ИмяТаблицы) <> Неопределено Тогда
        Если ЗначениеЗаполнено(УзелПланаОбмена) И ЗначениеЗаполнено(НомерСообщения) И ЗначениеЗаполнено(ДанныеУдаляемыеИзРегистрации) Тогда
            
            Запрос = Новый Запрос;
            Запрос.Текст ="ВЫБРАТЬ
            |    Изменения.Ссылка КАК Объект,
            |    Изменения.НомерСообщения КАК НомерСообщения
            |ИЗ
            |    Справочник." + ИмяТаблицы + ".Изменения КАК Изменения
            |ГДЕ
            |    Изменения.Узел = &Узел
            |    И Изменения.НомерСообщения > 0
            |    И Изменения.НомерСообщения <= &НомерСообщения
            |    И Изменения.Ссылка В(&ДанныеУдаляемыеИзРегистрации)
            |";
            Запрос.УстановитьПараметр("Узел", УзелПланаОбмена);            
            Запрос.УстановитьПараметр("НомерСообщения", НомерСообщения);
            Запрос.УстановитьПараметр("ДанныеУдаляемыеИзРегистрации", ДанныеУдаляемыеИзРегистрации);
            
            Выборка = Запрос.Выполнить().Выбрать();
            Пока Выборка.Следующий() Цикл
                ПланыОбмена.УдалитьРегистрациюИзменений(УзелПланаОбмена, Выборка.Объект);    
            КонецЦикла;    
            
        Иначе
            РезультатФункции = Ложь;    
        КонецЕсли;          
    Иначе
        РезультатФункции = Ложь;    
    КонецЕсли;
    
    Возврат РезультатФункции;
    
КонецФункции
1 mzelensky
 
06.04.21
12:48
После запуска этого механизма стала возникать ошибка блокировки:

Ошибка при вызове метода контекста (ВыбратьИзменения): Конфликт блокировок при выполнении транзакции:
Microsoft SQL Server Native Client 11.0: Транзакция (идентификатор процесса 55) вызвала взаимоблокировку ресурсов блокировка с другим процессом и стала жертвой взаимоблокировки. Запустите транзакцию повторно.

Т.е. блокировку вызывает вот эта строчка:

ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель, ЗаписьСообщения.НомерСообщения, ДанныеРегистрации);

Нужна она мне для того, чтобы выбираемым данным назначить номер сообщения, по которому потом будет происходить зачистка.
2 mzelensky
 
06.04.21
12:52
Поиски в интернете показали, что Да "ПланыОбмена.ВыбратьИзменения" вызывает блокировку.

Но почему она длительная и мешает и как можно адекватно обойти ее - не понятно
3 fisher
 
06.04.21
12:57
Еще бы она не вызывала блокировку. Она же пишущая.
А вот почему другой процесс в нее упирается и какой именно процесс - вопрос.
Релиз, платформа, режим блокировок?
4 mzelensky
 
06.04.21
13:05
(3) "Релиз, платформа, режим блокировок" - платформа 8.3.15, режим блокировок "Автоматический"

"какой именно процесс в нее упирается" - могу предположить .что механизм, который регистрирует изменения в узел.

Понятно, что она пишущая. Не понятно, почему она на столько "блокирующая".
5 mzelensky
 
06.04.21
13:06
Как лучше обойти проблему с присвоением номера выбираемым данным я не нашел. Во всех источниках применяется примерно такая же логика.
6 FIXXXL
 
06.04.21
13:25
(1) сделай обмен почаще, что бы порцайки не такие большие были
таблица плана обмена блокируется вся и наглухо... очень узкое место во всей концепции обменов на Планах
7 fisher
 
06.04.21
13:31
В режиме блокировок "Автоматический" для дедлока достаточно, чтобы оба процесса успели параллельно прочитать что-то нужное друг-другу для записи.
В управляемых блокировках это бы возникло только если бы они успели записать что-то нужное друг-другу для записи (так как де-факто управляемые блокировки сейчас на версионнике работают).
Но даже для первого варианта вроде эти звезды свести непросто. Хотя "Автоматический" еще эскалировать любит. Такое ощущение, что у тебя какие-то массированные пишущие регламенты крутятся, которые одно и то же могут перезаписывать. В итоге и таблица изменений постоянно большая и куча изменений тех же данных постоянно прилетает. Если это так, то попробуй развести их по времени хотя бы.
(6) Если бы она блокировалась вся и наглухо - то дедлоков бы не было. Был бы просто большой тайм-аут на блокировке и в худшем случае "опоздавшая" транзакция отваливалась бы по тайм-ауту.
8 H A D G E H O G s
 
06.04.21
13:32
Добавить в

Запрос.Текст ="ВЫБРАТЬ ПЕРВЫЕ 3000
            |    Изменения.Ссылка КАК Объект
            |ИЗ
            |    Справочник." + ИмяТаблицы + ".Изменения КАК Изменения
            |ГДЕ
            |    Изменения.Узел = &Узел";

ДЛЯ ИЗМЕНЕНИЯ
9 H A D G E H O G s
 
06.04.21
13:33
Это просто пучок Ванги в космос в надежде, что у тебя просто дедлок по повышению уровня изоляции.
10 fisher
 
06.04.21
13:39
(9) Тогда надо такое сделать одним запросом по всем выгружаемым справочникам. Тогда гарантия будет.
11 fisher
 
06.04.21
13:41
А зачем так вообще сделано? Зачем выгружать только справочники?
Почему вообще не свести это к единственному ВыбратьИзменения()?
12 Serg_1960
 
06.04.21
13:44
Автор реплику справочников базы данных делает?
13 fisher
 
06.04.21
13:45
А ЗаполнитьСтруктуруИзмененийДляУзла_Справочники() случаем не в транзакции вызывается?
14 mzelensky
 
06.04.21
13:47
(11) А разница?
15 mzelensky
 
06.04.21
13:48
(13) Уже проверил - программно не увидел такого.
16 mzelensky
 
06.04.21
13:49
Есть ли какой-то принципиально другой вариант выбрать данные из плана обмена с присвоением номера сообщения?

Я вот что-то не вижу альтернатив. Прям альтернатива - убрать к чертям эти планы обмена и делать все на обычном РС.
17 fisher
 
06.04.21
13:52
(15) Странно. Тогда действительно разницы быть не должно. Тогда действительно может помочь совет (8)
18 mzelensky
 
06.04.21
13:57
(17) Попробую (8)

"Такое ощущение, что у тебя какие-то массированные пишущие регламенты крутятся, которые одно и то же могут перезаписывать. В итоге и таблица изменений постоянно большая и куча изменений тех же данных постоянно прилетает. Если это так, то попробуй развести их по времени хотя бы."

Эти планы для регистрации элементов к выгрузке на сайт. Регламент выгрузки стартует каждые 3 минуты. Обычно очередь не очень большая, до 1000 элементов. Но иногда бывают "большие обмены", для этого ограничил размер порции 3000 элементами.

Механизм работает уже давно и довольно стабильно, но вот нашел одну "дырку", закрыть которую решил внедрением "ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель, ЗаписьСообщения.НомерСообщения, ДанныеРегистрации);" (ранее этой конструкции не было и из плана обмена удалялись все выгруженные элементы, без контроля НомераСообщения). "Дырку" закрыл, но появились ошибки блокировки.
19 Serg_1960
 
06.04.21
14:02
Каждые три минуты у Вас вносятся изменения в тысячу и более записей справочников? Извини за вопрос не в тему: а что это у вас такое вообще?
20 fisher
 
06.04.21
14:06
(18) Только раз вышестоящей транзакции нет, то для (8) нужно запрос и регистрацию обрамить в транзакцию.
21 mzelensky
 
06.04.21
14:06
(19) К чему удивления? Ты не видел интернет-магазины у которых "новый заказ" падает каждые 2-3 секунды? В заказе от 1 до 10 единиц товара. Дальше идет обработка всего этого.

+ Розничные магазины - 30 штук.
+ Оптовый отдел.
22 fisher
 
06.04.21
14:06
Тьфу. Запрос и выборку изменений.
23 fisher
 
06.04.21
14:07
(21) Обычно при этом принято изменять документы, а не справочники.
24 mikecool
 
06.04.21
14:07
емнип, но могу ошибаться - транзакция активна до окончания перебора выборки изменений
25 mzelensky
 
06.04.21
14:08
(19) "у Вас вносятся изменения в тысячу и более записей справочников" - не изменения вносятся в справочники, а возникают события, при которых элементы справочников нужно зарегистрировать к выгрузке во внешнюю системы.
26 mzelensky
 
06.04.21
14:09
(24) У меня вообще нет перебора выборки изменений


ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
                Запись = Новый ЗаписьXML;
                Запись.УстановитьСтроку();
                ЗаписьСообщения.НачатьЗапись(Запись, УзелПланаОбмена);
                
                ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель, ЗаписьСообщения.НомерСообщения, ДанныеРегистрации);
                
                РезультатФункции.Вставить("ДанныеРегистрации", ДанныеРегистрации);
                РезультатФункции.Вставить("НомерИсходящегоСообщения", ЗаписьСообщения.НомерСообщения);
                
                ЗаписьСообщения.ЗакончитьЗапись();
                Запись.Закрыть();
                
                ВыборкаИзменений = Неопределено;
                ЗаписьСообщения  = Неопределено;
                Запись              = Неопределено;
27 Serg_1960
 
06.04.21
14:09
Я понял, не нужно повторять.
28 fisher
 
06.04.21
14:11
(25) > возникают события, при которых элементы справочников нужно зарегистрировать к выгрузке во внешнюю системы
Зачем? Они поменялись? Почему? Или это банальная рекурсивная выгрузка всей используемой в заказах НСИ? Тогда зря.
29 mzelensky
 
06.04.21
14:12
(28) Сейчас не в этом вопрос. Давай не будем углубляться.
30 mikecool
 
06.04.21
14:13
(26) значит пришло время регистрацию изменений переделать на регистр сведений
31 mzelensky
 
06.04.21
14:16
(30) Да, было бы здорово перевести на РС.

Если победить блокировки не удастся, то, видимо, придется именно так и сделать.

Вообще механизм планов обмена какой-то тупиковый. Метода написана 10 лет назад и никакой эволюции.
32 fisher
 
06.04.21
14:20
(29) Тогда просто попробуй (8), обрамив чтение и выборку в транзакцию. По-идее, это должно заставить процессы телебонькать таблицу изменений по очереди, а не на брудершафт.
(30) На РС у тебя тоже могут возникнуть похожие проблемы
(31) Метода была написана еще в 7.7
Эволюция автомата калашникова не может происходить бескомпромиссно. К более продвинутому инструменту у тебя будет еще больше вопросов.
33 Ёпрст
 
06.04.21
14:29
(0) а зечем тебе механизм сообщений ?

Просто сам в коде удаляй регистрацию, если на сайт загрузилось и привет.
Тупо, план обмена регистрирует все изменения, ты их выгружаешь запросом на сайт и потом, по этой же выборке удаляешь регистрацию после обмена с сайтом. И Никаких номеров сообщений..
34 Kassern
 
06.04.21
14:30
(33) а что будет, если в момент выгрузки изменений зарегистрируются новые? Без сообщений, данные изменения просто похерятся
35 Cyberhawk
 
06.04.21
14:30
Выбирай не по 3000, а по 1000
36 Ёпрст
 
06.04.21
14:31
(34) И че ? Улетят при следующем обмене. Он отправит на сайт, только то, что запрос выгреб и по этой же выборке удалит изменения.
37 Ёпрст
 
06.04.21
14:31
И ничего там не херится.
38 Serg_1960
 
06.04.21
14:32
У автора есть простой выход: не пытаться втиснуть свой распухший обмен в регламент "каждые три минуты", а делать очередной обмен через три минуты после окончания предыдущего.
"Ну вот и славно! До свиданья... Да, а кислород попробуйте... и ванны." - и запись всех изменений порциями в транзакции.
39 fisher
 
06.04.21
14:34
(33) У него так и было. Смотри (18). Но что-то он провтыкал, что таким образом решил полечить.
40 Ёпрст
 
06.04.21
14:34
+ если по какой-то причине, на сайт загрузить не удалось, то просто не удаляешь регистрацию изменений.
Я у себя именно так и делал. И никаких номеров сообщений. Только узел обмена и привет.
41 Kassern
 
06.04.21
14:36
(37) вот у тебя есть документ прихода, ты запустил выгрузку по плану обмена, формируешь файлик с остатками в разрезе номенклатуры и бац, в этот момент отменяют данный приход, но ты это изменение по документу не отработал и взял очистил полностью все изменения в плане обмена после успешной выгрузки. Далее ты изменения по этому документу не получишь, пока заново документ не перезапишешь. Поэтому и придумали номера сообщений, когда ты получаешь изменения, новые записи в план обмена уже попадают в разрезе нового номера сообщения.
42 Kassern
 
06.04.21
14:38
(41) а далее весь букет неприятностей связанный с не верным остатком и отмененными заказами
43 Ёпрст
 
06.04.21
14:40
(41) какой нах приход и тырнет магазин ?
44 Serg_1960
 
06.04.21
14:42
*(38) хочу напомнить: автор формирует искусственно "порции" измененных данных, случайным образом попавших в выборку - имхо, на три минуты (а может быть и более) можно забыть про целостность и не противоречивость данных...
45 mzelensky
 
06.04.21
14:45
(33)(39)(40)

Возможна следующая ситуация:

В плане обмена зареганы товары "Т1", "Т2" и "Т3". Стартует обмен, выбирает все 3 элемента - посылает на выгрузку и ожидает ответа от внешней системы о успешном получении (все синхронно). Далее успешно выгруженные данные удаляются из плана обмена.

А в момент между "выбирает все 3 элемента - посылает на выгрузку" и "успешно выгруженные данные удаляются из плана обмена" возникает изменение элемента "Т2" (т.е. возникает потребность снова ег овыгрузить). И вот если НЕ использовать "номера сообщений", то в конце система просто затрет все 3 элемента. И Второй раз элемент "т2" уже не выгрузится.
46 Kassern
 
06.04.21
14:46
(45) о чем я и писал в (41)
47 mzelensky
 
06.04.21
14:46
(46) ну да.
48 Ёпрст
 
06.04.21
14:47
(45) да не вопрос, если этого боишься, то сразу грохай изменения. Потом выгружай на сайт, если не удачно - зарегь их. Все данные у тебя будут в выборке запроса.
49 mzelensky
 
06.04.21
14:47
И решить это можно либо "Номером сообщения" - если использовать планы обмена. Либо обычной "Дата регистрации в очереди", если использовать РС.
50 Kassern
 
06.04.21
14:47
в свое время настраивал крупный хаб по обмену остатков поставщиков, где матрицы товаров исчислялись десятками тысяч. Несколько крупных оптовиков обменивались остатками между собой. Вот там номер сообщения для обмена был критически важен
51 mzelensky
 
06.04.21
14:49
(48) Плохая политика. Мне кажется так менее надежно.
52 Ёпрст
 
06.04.21
14:49
(51) чем ? Что за пару мс у тебя что-то не зарегится ? У тебя там по 100'000 справочников летит всегда в обмене ?
53 Kassern
 
06.04.21
14:50
(48) что значит удачно, неудачно? Выгрузка в основном всегда удачная, только в момент ее реализации могут быть еще изменения которые при очистке изменений в плане не попадут в следующую выгрузку, или я чего то не понимаю?
54 mzelensky
 
06.04.21
14:50
(44) Вот это вообще не понял. О какой целостности и противоречивости речь?
55 Ёпрст
 
06.04.21
14:51
(53) это значит, что http запрос вернул не 200.
56 Ёпрст
 
06.04.21
14:51
тырнет у тебя отвалился, еще чего
57 mzelensky
 
06.04.21
14:52
(53) Не удачная - это обработка ситуации, что на "принимающей" стороне произошел сбой\ошибка и данные не загрузились. Такое тоже бывает. Например, сайт "упал"
58 mzelensky
 
06.04.21
14:54
(52) Я полагаюсь на следующее - "гарантированно приняли данные - тогда удалили из очереди". А если удалять сразу, то больше вариантов потерять данные, если где-то что-то пойдет не так.
59 Kassern
 
06.04.21
14:54
(57) в этом случае вообще никаких проблем нет, не очищаешь изменения и все. Я же говорю про случаи, когда в момент выгрузки происходят изменения, чем более нагруженная выгрузка по времени выполнения, тем больше шансов на такие моменты
60 Kassern
 
06.04.21
14:57
(59) я прост не вижу проблемы в использовании номеров сообщений, получаешь изменения по последнему номеру, обрабатываешь их, если удачно отправил - очищаешь изменения с этим номером.
61 Serg_1960
 
06.04.21
14:58
(54) Это просто для понимания: если есть изменения - то они должны быть переданы все и сразу, иначе у Вас может возникнуть ситуация, когда логически связанные между собой изменения будут "разорваны" - окажутся в различных сеансах обмена данными. Самый негативный момент - когда может возникнуть ситуация, что ранее зарегистрированное изменение не попадет ни в первую, ни во вторую "порцию" сеанса обмена - выборка таблицы изменений ведь по природе своей - случайна.
62 Kassern
 
06.04.21
14:59
(61) это что то новенькое, первый раз такое слышу...можно на реальном примере?
63 Serg_1960
 
06.04.21
15:07
(62) Это совсем не новость :( На реальном примере? Например, рИБ-обмен, особенность обмена: документы и их движения - автономны и независимы друг от друга. И всегда есть вероятность между обменами получить новые движения без изменения самого документа и/или измененный документ со "старыми" движениями. Само собой разумеется, что  после очередного обмена всё само собой нормализуется.
64 Kassern
 
06.04.21
15:13
(0) Блокировки управляемые у тебя?
Почитай вот эту статью, может разрешишь проблему с блокировками, тут в общих словах более менее разжевано, как работает план обмена со скулем
https://infostart.ru/1c/articles/561460/
65 Kassern
 
06.04.21
15:16
(64) + еще вот тут есть схожая проблема и решение
https://forum.infostart.ru/forum9/topic230643/
66 Serg_1960
 
06.04.21
15:34
Попытка автора читать и писать изменения "порциями" никоем образом не изменяет ситуацию с блокировками.
67 Kassern
 
06.04.21
16:00
(66) насколько я понял, блокировка происходит при записи номера сообщения, когда получаешь выборку изменений. При управляемых блокировках, таблица не должна блокироваться, поэтому и ошибки с блокировками быть не должно
68 Serg_1960
 
06.04.21
18:08
(67) Там нет единой таблицы как таковой. Имхо, в (64) об этом прямо сказано: ПланыОбмена.ВыбратьИзменения() поочередно обрабатывают каждую из таблиц изменений метаданных, а SQL Server, соответственно, для каждой из этих таблиц открывает/закрывает транзакцию - отсюда и эксклюзивные транзакционные блокировки таблицы.
69 Garykom
 
гуру
06.04.21
18:12
(25) хрень какая то зачем сами элементы справочников повторно выгружать?
не логичнее документы?
70 Garykom
 
гуру
06.04.21
18:12
(69)+ или у вас остатки в номенклатуре? :)
Здесь можно обсудить любую тему при этом оставаясь на форуме для 1Сников, который нужен для работы. Ymryn