При работе в клиент-серверной архитектуре 1С:Предприятие часто возникают ситуации, когда параллельная запись в регистр сведений вызывает критические ошибки TTIMEOUT. В данной статье мы разберем, почему возникают такие конфликты и как правильно настраивать управляемые блокировки для обеспечения стабильной работы системы.
Прежде всего, важно уяснить, что управляемые блокировки в 1С не имеют прямой связи с физическими блокировками таблиц в СУБД. Они управляются менеджером блокировок сервера 1С — процессом rmngr. Этот механизм использует служебную таблицу в оперативной памяти сервера приложений. Когда одна транзакция запрашивает блокировку, менеджер проверяет состояние этой таблицы. Если ресурс уже занят, транзакция встает в очередь. Если время ожидания превышает допустимый предел, мы получаем ошибку таймаута.
Рассмотрим, почему установка блокировки по всем измерениям регистра часто приводит к обратному эффекту — росту числа конфликтов:
Recorder приводит к тому, что менеджер блокировок может блокировать более широкие области, чем требуется для конкретной записи.rmngr, тем больше вероятность того, что система применит эскалацию, заблокировав значительно больший объем данных, чем необходимо для выполнения текущей операции.Для исправления ситуации попробуем применить следующие подходы:
Вместо того чтобы блокировать абсолютно все измерения регистра, попробуем выделить только те, которые действительно критичны для обеспечения целостности данных. Рассмотрим пример правильного (с точки зрения минимизации) кода:
// Инициализация объекта блокировки
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.торо_ПериодыПланированияППР");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = ПланРемонтов;
// Указываем только ключевые измерения, которые однозначно определяют набор записей
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("ОбъектРемонтныхРабот", "ОбъектРемонтныхРабот");
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("ВидРемонтныхРабот", "ВидРемонтныхРабот");
Блокировка.Заблокировать();
Если проблема сохраняется, необходимо проанализировать логи TLOCK и TTIMEOUT в технологическом журнале. Обратите внимание на колонку Locks. Если вы видите, что транзакции пересекаются по полям, которые вы даже не накладывали явно, это может указывать на то, что платформа автоматически захватывает избыточные ресурсы. В этом случае:
Проверьте структуру метаданных: Убедитесь, что все измерения, по которым вы накладываете блокировку, действительно являются измерениями, а не реквизитами. rmngr работает только с измерениями регистра в пространстве DIMS.
Не забывайте, что управляемые блокировки удерживаются на протяжении всей транзакции. Если ваша транзакция Записать() включает в себя тяжелые вычисления, чтение больших объемов данных или обращение к другим высоконагруженным объектам, время удержания блокировки увеличивается.
Практический совет: Постарайтесь максимально вынести логику подготовки данных и расчетов за пределы блока НачатьТранзакцию() — ЗафиксироватьТранзакцию(). Внутри транзакции должны оставаться только запись данных и критически важные проверки.
Если после сокращения состава измерений конфликт всё равно возникает при попытке записи двух разных наборов, которые заведомо не должны пересекаться, высока вероятность ошибки в самой реализации платформы. Мы рекомендуем:
bugboard от 1С.Помните: индексы в СУБД никак не влияют на работу менеджера управляемых блокировок, так как rmngr хранит информацию о них исключительно в оперативной памяти. Однако наличие индексов необходимо для быстрого поиска данных, что косвенно уменьшает длительность транзакции и, как следствие, снижает риск появления таймаутов.