gifts2017

Одно из простых решений проблемы зависания 1С из-за конфликта блокировок

Опубликовал Дмитрий Деменёв (ddemenev) в раздел Администрирование - Оптимизация БД (HighLoad)

Простой и эффективный способ решения проблемы блокировок 1С по номенклатуре, контрагентам с помощью формирования динамической очереди проведения документов без наложения управляемых блокировок 1С на основные регистры хранения данных.

Вводные: конфигурация УПП, 8.2, типовые алгоритмы существенно изменены различными разработчиками; высокая скорость изменения остатков номенклатуры + несколько небольших топовых списков товаров, часто повторяющихся в документах товародвижения

В общем, все основные причины блокировок в наличии, и как следствие, постоянные зависания системы .

Как победили:

1. Провели максимальную оптимизацию кода процедур записи/проведения документов товародвижения (ускорились в 3 и более раза)

2. Исключили возможность одновременного помещения в регистры записей с одинаковыми измерениями путем построения и контроля очереди  проведения документов.

Первое пропущу, по этому вопросу в сети тонны информации.

Вторую проблему решили несколько необычным способом с помощью управляемых блокировок.

Было решено не накладывать принудительные блокировки на основные таблицы хранения в связи с их большим размером, частыми чтениями, проблемами контроля различных блокировок и пр.
Т.к. при создании объектов программных блокировок 1С не учитывает, заполнен объект блокировки, или нет, были созданы служебные регистры сведений с измерениями проблемного типа. Новые регистры не содержат данных и используются только в качестве объектов управляемых блокировок 1С. В модули  документов  был добавлен код создания блокировки, для примера код РТиУ:

Процедура ПриЗаписи(Отказ)
    Если Проведен Тогда
        Попытка
            Блокировка = Новый БлокировкаДанных;
            ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.БлокировкаПроведенияРеализаций");
            ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
            ЭлементБлокировки.ИсточникДанных = Товары;
            ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
            Блокировка.Заблокировать();
        Исключение
            Отказ = Истина;
            Возврат;
        КонецПопытки;
    КонецЕсли;

При проведении очередного документа система фиксирует блокировку регистра "БлокировкаПроведенияРеализаций" по измерению "Номенклатура" и списку товаров документа. Блокировка живет до завершения текущей транзакции, при этом попытки наложить на служебный регистр новую программную блокировку с хотя бы одним товаром, присутствующим в списке текущей "активной" блокировки, динамически формируют очередь проведения по основным регистрам (по умолчанию время ожидания создания новой блокировки, если, не ошибаюсь, 30 сек.). При работе системы по разным непересекающимся спискам номенклатур формируются разные очереди документов, которые проводятся параллельно.

На платформе 8.3 не пробовал, но, думаю, и там будет работать.

Надеюсь, эта информация окажется для Вас полезной. Удачи!

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Алексей Новиков (Новиков) 15.11.16 10:11
Приветствую! А можно скрин структуры регистра из примера?
2. Сан Саныч (herfis) 15.11.16 11:01
Было решено не накладывать принудительные блокировки на основные таблицы хранения в связи с их большим размером, частыми чтениями, проблемами контроля различных блокировок и пр.

Странное решение. Мне кажется, что вы элегантно решили несуществующую проблему. Наложение точно таких же управляемых блокировок на основные таблицы, а не на пустой регистр, никак не должно было сказаться на эффективности, ИМХО.
Сервис управляемых блокировок, по-идее, прямо не связан с СУБД и используемыми таблицами. Эта штука и так стоит в стороне и нет необходимости пытаться отодвинуть ее еще дальше.
Вам просто показалось проще прикрутить еще один слой, чем разбираться и грамотно править существующий.
ЗЫ. Ах да, вполне возможно, что это и оправданное решение, чтобы не курочить типовую. Я лишь указываю, что использовать отдельные пустые структуры само по себе не предполагает повышение эффективности.
Silenser; _also; Yashazz; Nick_N; zqzq; Andreynikus; sheffchik; asved.ru; mrDSide; Dach; hulio; alex-l19041; ddemenev; +13 Ответить 2
3. Дмитрий Деменёв (ddemenev) 15.11.16 11:22
(2) herfis, вы правы во всем, частично решение вызвано недостатком опыта в настройке и управлении блокировками, частично недостатком времени на глубокий анализ проблемы в связи с большим потоком задач по разработке ПО. Я потому и определил способ, как простой - не у всех есть возможность длительное время заниматься серьезной отладкой гибких блокировок. Для моей системы это не первая попытка решить проблему и первое решение, которое принесло желаемый результат без побочных негативных эффектов.
4. Дмитрий Деменёв (ddemenev) 15.11.16 12:23
(1) Новиков, в моем случае, это независимый непериодический регистр сведений с одним измерением "Номенклатура"
Прикрепленные файлы:
5. Andrey BedaNastala (Lem0n) 15.11.16 16:07
"проведения документов без наложения управляемых блокировок 1С на основные регистры хранения данных"
Движения.Записать() - наложит управляемые блокировки
Вместо ожидания на "основных регистрах" получаем ожидание на блокировках на регистре сведений, т.е. очередь ожидания разбита: одни ждут на регистре сведений , другие - на "основных регистрах" (если нет представленного кода в др документах, двигающих "основные регистры").
Предложу решение лучше этого (ни в коем случае не считаю его правильным) - Администрирование - параметры информационной базы - ожидание блокировки в сек. увеличить
6. bulpi bulpi (bulpi) 15.11.16 16:08
(2)
Нет, это не странное решение. Ты типовую УПП смотрел ? При попытке разобраться с алгоритмами проведения возникает устойчивое желание завязать с 1с навсегда :)

Вопрос к автору : а почему ПриЗаписи, а не ОбработкаПроведения ?
7. Дмитрий Деменёв (ddemenev) 16.11.16 07:33
(6) bulpi, место кода, в котором необходимо разместить блокировку, зависит от особенностей учета товарооборота в тек. БД. В моем случае с целью повышения производительности отключен контроль остатков и размещение блокировки в процедуре "При записи" принесло максимальный эффект.
8. Сергей Огородников (Serg O.) 16.11.16 14:57
1) блокировка держится 20 сек ( в 1С 8.2 )

2) вопрос - в этот регистр идёт запись товаров или нет?
если нет, то при наложении блокировки на пустую таблицу - ВСЯ таблица всегда блокируется...
а не только по этим товарам

3) "с целью повышения производительности отключен контроль остатков" - вот это у вас и тормозило скорее всего
не понятно... как вы без контроля живете

скорее всего у вас после отключения контроля остатков - просто НЕ возникает блокировки на 20 и более секунд никогда

4) для точного ответа на вопрос что и где блокируется - есть инструмент (бесплатный) для анализа блокировок
http://www.gilev.ru/timeoutlock/
Gilev.Vyacheslav; +1 Ответить 1
9. Дмитрий Деменёв (ddemenev) 16.11.16 15:40
(8) Serg O., "в этот регистр идёт запись товаров или нет?" - нет, запись в регистр не производится, регистр пустой. При этом блокировка накладывается только на список текущих товаров, при принудительном прерывании записи тек. документа (по точке останова), документы с другим набором продукции проводятся. Документы с товарами блокировки при проведении попадают в состояние ожидания. От контроля остатков отказались более 4 лет назад, т.к. с включенным контролем работать было невозможно. Ежедневно в пиковые часы нагрузки у нас беспрерывная одновременная сборка заказов на 20 местах комплектовки в течение 4-6 ч., при этом обрабатывается до 2000 заказов. Описанная система блокировки запущена в феврале этого года, и совместно с оптимизацией кода решила проблему блокировок по номенклатуре полностью. Среднее время проведения РТиУ после оптимизации - около 1 с.
10. Вячеслав Гилёв (Gilev.Vyacheslav) 16.11.16 15:55
(0) лучше бы Вы версионирование включили http://www.gilev.ru/snapshot1c/
Danil.Potapov; +1 Ответить 2
11. Дмитрий Деменёв (ddemenev) 16.11.16 16:34
(10) Gilev.Vyacheslav, Спасибо, в настоящее время одной из задач стоит включение контроля остатков при комплектации. Обязательно воспользуюсь Вашим советом. Немного смущает использование базы tempdb для хранения версий, в связи с тем, что для нас это одно из узких мест, несмотря на расположение темповой бд на быстрых SSD дисках. Но обязательно попробую.
12. Caponid V (caponid) 16.11.16 16:40
Может быть это для кого-то и плохое решение, но как я понимаю в данном случае это было хоть и вынужденное, но рабочее.
Я вижу единственное применение данного метода - это временный "костыль" для исключения взаимоблокировок - перенос взаимоблокировки в принудительную блокировку в обработчик "ПриЗаписи". т.е. взаимоблокировки сводятся к ожиданию на блокировке. Тут явно что то не то с кодом и порядком в проведении.

Финансисты в резко изменяющихся условиях могут диктовать сроки по изменению бизнес функционала - это вполне нормально.
Но они не всегда понимают риски в разработке такого ПО. По мере накопления таких вот "костылей" и увеличения базы все может в один момент, и скорее всего в "бизнес-время с максимальной нагрузкой" рухнуть. Ревью старого кода надо проводить на постоянной основе... а вот время, которое можно выделить, тут надо как то договариваться.

Sardukar; +1 Ответить
13. Вячеслав Гилёв (Gilev.Vyacheslav) 17.11.16 17:23
(11) ddemenev, альтернативой может быть размещение tempdb на RAM-диске
14. Виктор Григоренко (JohnGalt) 17.11.16 17:36
Очень помогает включение READ_COMMITTED_SNAPSHOT для бд MS SQL.
15. Яков Коган (Yashazz) 17.11.16 18:01
Раз эту тему посетил Гилёв, попробую узнать несколько моментов:
1. Если наложить управляемую блокировку, где одно из значений неверное (в источнике или через прямую установку) - она его проигнорирует и наложит, что сможет, или вообще не сработает?
2. Если наложить управляемую блокировку с одним источником, а потом в той же транзакции с другим, и эти два источника противоречат друг другу, то что будет - блокировка по "И", по "ИЛИ", по "XOR" или всегда актуальна только последняя по времени наложения?
3. Если наложить управляемую блокировку с указанием пустого значения, как она себя поведёт? Допустим, в регистре есть измерение, для которого разрешены пустые значения, ну и в условиях блокировки тоже пустое - нормально отработает или эскалирует? И что будет, если там многотипное измерение и значения даются блокировке пустые, но по-разному? Или "Неопределено", NULL итд?

Кто знает, расскажите. У меня тупо руки не доходят поэкспериментировать, совсем нет времени.
16. Дмитрий Деменёв (ddemenev) 17.11.16 19:49
(13) Gilev.Vyacheslav, спасибо за советы, очень полезные и по теме. Ценнее другое. Лично для меня убиты предрассудки, что Ваша команда, Ваш интернет ресурс функционируют с исключительной целью получения прибыли за счет сложных решений не столь сложных проблем. Ошибался. Обязательно буду использовать Ваш сайт, как источник экспертных знаний.
17. Ярослав Володимирович (myr4ik07) 19.11.16 22:36
(10) Gilev.Vyacheslav, и тут Слава ты не смог не зарекламироваться, не хватило терпения, что бы не наследить и тут
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа