При выполнении обмена данными в распределенной информационной базе (РИБ) или при попытке прочитать зарегистрированные изменения через специализированные обработки (например, РегистрацияИзмененийДляОбмена8_2) пользователи могут столкнуться с критической ошибкой:
«Конфликт блокировок при выполнении транзакции: Превышено максимальное время ожидания предоставления блокировки».
Ошибка часто проявляется в момент вызова метода ПрочитатьИзменения() или при выполнении прямых запросов к виртуальным таблицам изменений объектов конфигурации. Разберем причины возникновения этой ситуации и пошаговые варианты ее устранения.
Проанализируем типовой участок кода, на котором происходит сбой при чтении данных узла обмена. При подсчете или выборке измененных объектов выполняется обращение к таблицам регистрации изменений:
Функция ПолучитьКоличествоЗарегистрированныхОбъектовДляМетаданногоПоУзлу(МетаданныеОбъекта)
Запрос = Новый Запрос();
ИмяТаблицы = ПолучитьПоМетаданномуНазвание(МетаданныеОбъекта);
Если ПустаяСтрока(ИмяТаблицы) Тогда
Возврат 0;
КонецЕсли;
ИмяТаблицы = ИмяТаблицы + "." + МетаданныеОбъекта.Имя + ".Изменения";
Запрос.Текст = "ВЫБРАТЬ
| Количество(*) КАК Количество
|ИЗ
| " + ИмяТаблицы + " КАК РегистрацияИзменений
|ГДЕ
| РегистрацияИзменений.Узел = &Узел";
Запрос.УстановитьПараметр("Узел", УзелОбмена);
ТаблицаДанных = Запрос.Выполнить().Выгрузить();
Если ТаблицаДанных.Количество() = 0 Тогда
Возврат 0;
Иначе
Возврат ТаблицаДанных[0].Количество;
КонецЕсли;
КонецФункции
В момент выполнения метода Запрос.Выполнить() происходит обращение к служебным таблицам СУБД (например, _ReferenceChngr, _DocumentChngr). Выясним основные причины возникновения таймаута:
Seq Scan), увеличивая время выполнения запроса свыше установленного таймаута блокировки.Если проблема проявилась сразу после перехода на проблемную версию платформы 1С (например, 8.3.9.2033 или 8.3.9.1850), наиболее надежным и быстрым решением является корректировка версии платформы:
8.3.8.1652) полностью устраняет конфликт блокировок при чтении таблиц планов обмена.Проанализируем параметры конфигурации в дереве метаданных. В ряде случаев платформа 1С при установленном режиме совместимости Версия 8.2.13 или Версия 8.2.16 накладывает блокировки по устаревшим правилам.
Версия 8.3.5 или выше (при условии, что код конфигурации адаптирован под данный режим).Настроим параметры СУБД в конфигурационном файле postgresql.conf для предотвращения дефицита разделяемой памяти под блокировки:
max_locks_per_transaction. По умолчанию он равен 64. Для баз 1С с разветвленной структурой метаданных и активным использованием РИБ увеличим значение до 256 или 512:
max_locks_per_transaction = 256
deadlock_timeout. Рекомендуемое значение для работы с 1С составляет 1s (1000 мс):
deadlock_timeout = 1s
postgresql.conf и выполним перезапуск службы СУБД.Если таблицы регистрации изменений содержат некорректные записи или поврежденные ссылки, очистим регистрацию для проблемного узла и зарегистрируем объекты заново программным способом:
// Полное удаление регистрации изменений по проблемному узлу
ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена);
// Выборочная регистрация только необходимых типов объектов
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, Метаданные.Справочники.Номенклатура);
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, Метаданные.Документы.РеализацияТоваровУслуг);
Рассмотрим вариант оптимизации кода при выборке данных узла обмена. Вместо полной выгрузки таблицы запроса в память через метод Выгрузить(), используем обход через выборку, а также избегаем выполнения тяжелых запросов внутри длительных транзакций:
ТаблицаДанных = Запрос.Выполнить().Выбрать();
Если ТаблицаДанных.Следующий() Тогда
Возврат ТаблицаДанных.Количество;
Иначе
Возврат 0;
КонецЕсли;
Для гарантированного выявления конкретного источника блокировок в сложных случаях настроим Технологический журнал с отслеживанием событий TLOCK и TTIMEOUT, что позволит определить точный контекст кода и имена таблиц, на которых сеансы ожидают освобождения ресурсов.