«Конфликт блокировок при выполнении транзакции» в 1С: причины и решение
Два или несколько сеансов одновременно пытаются изменить или прочитать с блокировкой одни и те же данные, и один из них не дождался освобождения. После двоеточия платформа указывает подробности: превышение времени ожидания или взаимоблокировку.
Текст ошибки
Причины
- Одновременное проведение документов, которые пишут в одни и те же регистры
- Долгие транзакции: массовое перепроведение, закрытие месяца, загрузка данных в рабочее время
- Конфигурация работает в автоматическом режиме блокировок, и СУБД блокирует больше записей, чем нужно
- Регламентные и фоновые задания пересекаются с работой пользователей
- Повисший сеанс удерживает блокировку
- Неоптимальные запросы без индексов, из-за которых СУБД блокирует целые таблицы
Что делать пользователю
- Подождите немного и повторите операцию: если конфликт был разовым, документ проведётся.
- Если ошибка повторяется у многих, сообщите администратору время и операцию. Возможно, в этот момент идёт тяжёлая обработка: перепроведение, закрытие месяца, обмен.
Что делать администратору
- Проверьте, какие сеансы и фоновые задания работали в момент ошибки: в консоли кластера серверов или обработке «Активные пользователи». Завершите повисшие сеансы.
- Перенесите тяжёлые операции (перепроведение, закрытие месяца, полную выгрузку обменов) на нерабочее время, разведите по времени регламентные задания.
- Для клиент-серверной базы проверьте обслуживание СУБД: обновление статистики и перестроение индексов на MS SQL Server или VACUUM ANALYZE на PostgreSQL. Устаревшая статистика приводит к плохим планам запросов и лишним блокировкам.
- Для детального анализа включите технологический журнал с событиями
TLOCK,TTIMEOUTиTDEADLOCK: в них видно, какие сеансы и на каких данных конфликтуют.
Что делать разработчику
Режим управления блокировками
В свойствах конфигурации посмотрите «Режим управления блокировкой данных». Современные типовые конфигурации используют управляемый режим. Старые и самописные конфигурации в автоматическом режиме блокируют данные средствами СУБД, что даёт много конфликтов при параллельной работе. Переход на управляемый режим требует проверки кода, где нужна явная блокировка.
Блокируйте до чтения и как можно точнее
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ТоварыНаСкладах");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = Товары;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
ЭлементБлокировки.УстановитьЗначение("Склад", Склад);
Блокировка.Заблокировать();
// Только после этого читаем остатки и пишем движения
Чем точнее заданы поля блокировки, тем меньше сеансов будут мешать друг другу. Блокировка всей таблицы без отбора по измерениям быстро становится узким местом.
Сокращайте транзакции
- Не выполняйте внутри транзакции долгие вычисления, обращения к внешним сервисам и ожидание ответа пользователя.
- Массовые операции делите на порции с отдельной транзакцией на каждую.
- Порядок блокировок в разных документах держите одинаковым, тогда взаимоблокировки возникают реже.
Частые вопросы
Почему ошибка появляется только в конце месяца?
В это время выполняются тяжёлые регламентные операции, которые долго держат блокировки, а пользователи параллельно проводят документы. Разнесите операции по времени.
Помогает ли увеличение времени ожидания блокировки?
Иногда снимает разовые ошибки, но не устраняет причину. Если транзакции длинные, большее ожидание лишь замедлит работу всех пользователей.