Взаимоблокировки при обмене данными #772150


#0 by Lexusss
Имеем 1С Документооборот. Порядка 2,5 млн задач, 1000 пользователей. Режим блокировок - автоматический. MS SQL 2012 @ Win 2012. 100 гигов ОЗУ, много ядер и дисков. Распределенка на 3 переферийных узла. Собственно с распределенкой и проблема. Пользователи жалуются, что регулярно у них всплывает конфликт блокировок. Запустили ЦУП, поустраняли все очевидные косяки - стало попроще. Но дедлоки постоянно всплывают в ходе выполнения обмена, и очевидно, что блокировщик оставляет живой транзакцию обмена (как более нагруженную), а не пользователя. А пользователи получают некрасивую картинку и надобность опять жмакать кнопку Исполнено. Не хорошо это, решили мы, и стали дальше копать ЦУП, что ж там так взаимоблокируется. Получилась картинка, как по учебнику: взаимоблокировка из-за захвата объектов в разном порядке. Причина - две таблицы объекта задачи: основная таблица Task30 и ее таблица изменений TaskCh2018. При обычном выполнении задачи, система сначала пишет объект UPDATE T1 SET _Marked = ?, _Number = ?, и так далее... FROM dbo._Task30 T1 WHERE (T1._IDRRef = ? AND T1._Version = ?) и так далее (тут страшный RLS) Затем - таблица изменений UPDATE T1 SET _MessageNo = CAST(NULL AS NUMERIC(38,8)) FROM dbo._TaskChngR2018 T1 WHERE T1._IDRRef = ? AND (T1._NodeTRef = 0x00000007 AND T1._NodeRRef IN (?, ?, ?)) Все логично - записали объект, а затем записали, куда его отправлять по обмену. А вот при выгрузке РБД идет обратная история. ПланыОбмена.ЗаписатьИзменения творит обратную историю. Сначала пишет в таблицу изменений номер сообщения, который получат все объекты, пока что не попавшие в обмен: UPDATE T1 SET _MessageNo = ? FROM dbo._TaskChngR2018 T1 WHERE T1._NodeTRef = 0x00000007 AND T1._NodeRRef = ? AND T1._MessageNo IS NULL Потом узнает, что собственно надо выгружать SELECT T1._IDRRef FROM dbo._TaskChngR2018 T1 WHERE T1._NodeTRef = 0x00000007 AND T1._NodeRRef = ? А затем начинает читать сами объекты для выгрузки SELECT T1._IDRRef, T1._Version, T1._Marked, ... FROM dbo._Task30 T1 WHERE T1._IDRRef = ? Получается клинический дедлок - пользователь заблокировал основную таблицу и ждет освобождение таблицы изменений, обмен заблокировал таблицу изменений и ждет основную таблицу. Все эту регулярно повторяется и чудесно видно в ЦУП. Вопрос: кто сталкивался с этой бедой и как можно это победить? Учебник говорит, что надо организовать параллельное блокирование, но вроде бы типовые методы Записать в объекте и ЗаписатьИзменения в плане обмена не должны кофликтовать. Или мы первые, кто вздумал с этим бороться по уму, а не через костыли? Костыли то мы знаем как сделать, например та же отложенная регистрация на обмен, но как то не хочется ломать то, что должно работать и так.
#1 by samozvanec
такая тема интересная, чего все молчат то?
#2 by Lexusss
Уж очень узкоспециальная тема. Нужно знать и 1С, и SQL, и навыки работы в нагруженных БД, и еще и РБД в комплект. Видимо, будем писать в техподдержку 1С.
#3 by Cyberhawk
Чтобы не было "обмен заблокировал таблицу", нужно повышать частоту обмена и снижать кол-во объектов в порции обмена
#4 by milan
Можно еще в софтпоинт обратиться, это их сфера, помогут.
#5 by Рэйв
Переходите на управляемые блокировки - будет полегче
#6 by aleks_default
Да уж с 1000 пользователей и автоматические блокировки... Как вы еще работаете?
#7 by aleks_default
Хотя, это же Документооборот...
#8 by ptiz
На первый взгляд - переход на управляемые блокировки и наложение блокировок вручную. Но вот насколько оно будет конфликтовать с РБД....
#9 by aleks_default
У метода ЗаписатьИзменения есть второй параметр. С ним играться не пробовали?
#10 by bura_limon
на управляемые блокировки РБД кто первый заблокировал тому и флаг в руки
#11 by Lexusss
Извините, что редко забегаю. Тема все же оч актуальна. В базе три плана обмена: оперативный 1 раз в 30 секунд, полный 1 раз в 15 минут, обмен файлов - практически постоянно. Любой объект регистрируется лишь в одном из обменов - либо относится к полному, либо к оперативному, либо файловому. Оперативный гоняет лишь 2 вида бизнес-процессов и все задачи к ним, по максимуму нашинкован оптимизацией, работает по схеме "все со всеми" (то есть переферийки обмениваются друг с другом). Один цикл обмена "загрузка 4 обменников + выгрузка 4 обменников" занимает максимум 3-4 секунды. Куда уж меньше делать интервал - не знаю :D Файловый обменивает только версии файлов. Работает сам по себе, ни с кем ни конфликтует и вообще никому не мешает. Полный гоняет все остальное. Топология классическая звезда. Может затянуться и на минуту, и даже больше. В нем мы поставили по 50 объектов в транзакции. До этого блокировки были вообще постоянные. NodeTRef = 0x00000007 - это как раз полный обмен. Но дедлоки бывают как с полным, так и оперативным. Суть проблемы одна, и она никак не исправится с уменьшением периодичности или сокращением объема посылки. Все равно, если очередность захвата объектов отличается - дедлок неизбежен. Очередность при решении проблем - сам покопать, спросить у хорошего франча, написать на форум, написать в поддержку 1С, написать в Рарус :) Пока что я дошел только до третьего этапа. Если уж 1С пошлет (как обычно) - тогда буду обращаться к Гилеву. (5,6) Ручные блокировки не устраняют проблему дедлока с неправильной очередностью захвата. Ну и опять же, трудоемкость перевода на ручные блокировки очень большая. Я никак не могу осилить переезд Консолидации на полностью ручные блокировки, а там беда гораздо больше. Загрузка одного экземпляра тяжелого отчета блокирует такое количество страниц в бедном регистре, что даже и не знаю, помогут ли даже ручные блокировки. Да, документооборот гораздо проще с точки зрения оптимизации. Все в конце концов сводится к задачам, RLS и обменам. Исключив очевидные вещи, вроде взаимоблокировок обменов, рег заданий, устранив лишние вещи из обменов, мы сократили число взаимоблокировок с 10 в час до 6 в день, а уж время ожидания на блокировках во время запросов - так вообще радикально. Это число объектов в транзакции. Игрались конечно. Самая первая вещь, на которую смотрели. (8,10) Что может дать ручное управление блокировками? У меня автоматическое накладывает блокировку на одну строку. Проще некуда. И именно с ней конфликтует обмен, который пытается наложить блокировку на ту же строку. Пример: пользователь создал задачу. После этого запускается обмен, который блокирует Chng по этой задаче, и начинает выгружать другие задачи. В это время, пока идет выгрузка, пользователь ВЫПОЛНЯЕТ эту задачу: при этом сначала блокируется и пишется сама задача, потом пытается в той же транзакции записать Chng. Но видит наложенную эксклюзивную блокировку на таблицу Chng со стороны обмена и ставится в ожидание. В это время идет обмен. Он доходит до того, чтобы выгружать эту конкретную задачу, и пытается сделать считывание задачи из основной таблицы. Видит блокировку, ранее наложенную пользователем, становится тоже на ожидание. Сервер SQL видит, что возник дедлок - смотрит у кого транзакция "толще". Это всегда обмен (он же большой и длинный, даже из 50 объектов, и меня это больше устраивает). А мелкого пользователя - выкидывает с ошибкой дедлоку и откатывает его транзакцию со всеми блокировками. Все это можно чудесно отследить в техжурнале, а прямо идеально все рисуется в ЦУП. Учебник говорит, что надо добиться идентичной последовательности блокировки объектов в транзакциях. В задаче она, очевидно, правильная - сначала объект в основной таблице, затем его chng. У обмена тоже есть своя логика - он сначала из chng должен понять, кого выгружать, а затем непосредственно выгружать из основной таблицы. И как тут организовать правильную последовательность блокировок - ума не приложу.
#12 by Fragster
а зачем 50 объектов в транзакции? чем не устраивает 1?
#13 by Lexusss
Высока вероятность нарушения целостности данных. База достаточно нагруженная, выловить потом расхождения в РБД - очень проблематично. Если в одной базе заявка утверждена, а в другую это никогда не придет - это катастрофа.
#14 by Digger
Когда у нас возникла проблема,  что у пользователей стали часто выскакивать блокировки при проведении документов и конфликтовать с обменом,   мы вынесли все это проведение в фон и отложенные регламенты.    Так что для пользователя все происходит нажал и забыл,  а программа сама уже с собой воюет в попытках допровести доки и обменяться.
#15 by aleks_default
У обмена тоже есть своя логика - он сначала из chng должен понять, кого выгружать - для этого нужна эксклюзивная блокировка? А у вас процедура обмена реализована через ПланыОбмена.ЗаписатьИзменения? А если использовать ПланыОбмена.ВыбратьИзменения тоже блокировка накладывается?
#16 by ptiz
"не устраняют проблему дедлока с неправильной очередностью захвата." - почему? Если мы захватили оба объекта до захвата одного из них выгрузкой РБД - выгрузка стоит и ждет. Может отвалиться по таймауту, но дедлока не будет. Если РБД захватила один из объектов, а мы пытаемся захватить сразу оба - мы ждем курим. Так же можем отвалиться по таймауту, но дедлока не будет.
#17 by Fragster
не будет расхождений, т.к. сообщение не будет прочитано и будет выгружено из источника еще раз с теми же данными.
#18 by D_Pavel
>> Чтобы не было "обмен заблокировал таблицу", нужно повышать частоту обмена и снижать кол-во объектов в порции обмена Это вообще никак не влияет. Количество объектов переданное например за час не изменится, и шанс пользователя напороться на блокировку тоже не изменится.
#19 by D_Pavel
Это придется переходить на управляемые блокировки. Не вариант.
#20 by MaxS
Распределенные 3 узла синхронизируются с центральной базой, в которой работают пользователи? И в этой ИБ блокироки? А если эту ИБ сделать служебной центральной для обменов, а пользователям в центре завести 4-ю распределённую ИБ?
#21 by MaxS
Давно делал - были проблемы с УПП распределенными обменами. В ЦБ постоянные блокировки и меняющиеся остатки при перепроведении документов. Сдеал в центре для пользователей базу с полным обменом УПП-УПП филиалы - это РБД, обменивающиеся со служебной ЦБ, где только обмены и перепроведения после обменов. И потом итог обменов незаметно подгружается полным обменом(с движениями регистров и без перепроведений) в пользовательскую ЦБ .
#22 by Fragster
самая простая методика перехода на управляемые: ставим режим конфигурации управляемые и автоматические, ставим у всего, кроме документов и "объектов, порождающих документы" (иногда такие есть) режим в управляемый. После этого уже станет намного лучше. Потом настраиваем техножурнал на ожидание блокировок и переписываем на управляемые ту часть документов, которые вызывает блокировки. После этого не спеша переписываем остальное. работы не так много, учитывая, что переписывать надо только то по чему идет контроль остатков, т.е. все приходные документы автоматом могут стать управляемыми вообще без кода.
#23 by Lexusss
Как сделать костыль -  я понимаю. Но уж очень не хочется воротить огород, если есть нормальное решени. Используется ЗаписатьИзменения. Ваш совет про ВыбратьИзменения, надеюсь, поможет. По крайней мере, если верить описанию в синтаксис помощнике, можно попробовать управлять блокировками. Сначала сам сделаю грязное чтение  изменений из chng, наложу блокировку на основную таблицу, затем выполню ВыбратьИзменения, а затем и выберу сами данные. Разве что боюсь, что в одной транзакции это придется делать. Но по крайней мере шансы есть. Спасибо. Ручное управление блокировками может решить проблему эскалации блокировок или повышения уровня блокировок. Но никак неправильную последовательность. Чтите теорию. Ой не зря в помощнике написано, что возможно возникновение расхождений. Где то у нас уже такое всплывало. Лень вспоминать, но проблема в том, что в момент обмена вносятся изменения в БД, которые потом не подхватываются в очередной обмен. Центральная база - ОЧЕНЬ большая на очень быстром дисковом массиве. Делать лишнюю реплику - очень дорого. Надеюсь наш документооборот не придется переписывать. Страшно подумать, сколько там кода - неск десятков бизнес-процессов, куча навесов в виде обменов, интеграций, связей... Вобщем - проще решить проблему обменов или отложенную регистрацию на обмен. Фактически - это то же грязное чтение таблицы изменений. Так что, еще раз спасибо aleks_default за идею. ПОпробуем потестировать, ближе к середине следующей недели апну тему.
#24 by TormozIT
Про ВыбратьИзменения правильно советуют. Там будет заметно выше управляемость процессом обмена, а расхождений не появится. Количество объектов на транзакцию влияет на вероятность кратковременного нарушения логической целостности данных в базе (например уже загружен документ, который ссылается на еще не загруженную номенклатуру).
#25 by MaxS
Не настаиваю, конечно. Но для оперативной работы какой объём данных нужен? Возможно 5% от основной базы. Т.е. вторую базу сделать свёрнутой. Это как один из вариантов.
Тэги: 1С 8
Ответить:
Комментарии доступны только авторизированным пользователям

В этой группе 1С