В практике разработки на платформе 1С:Предприятие 8.3 нередко встречается ситуация, когда стандартный, на первый взгляд, код вызывает «мертвое» зависание системы. Особенно часто это происходит при работе с системными регистрами, такими как РегистрСведений.ТаблицыГруппДоступа. Проанализируем ситуацию: код выполняется в транзакции, регистр абсолютно пуст, но команда Заблокировать() останавливает работу сеанса до истечения времени ожидания. Выясним причины этого поведения и разберем по шагам, как устранить проблему.
Рассмотрим фрагмент кода, который чаще всего становится причиной обсуждения:
Блокировка = Новый БлокировкаДанных;
Блокировка.Добавить("РегистрСведений.ТаблицыГруппДоступа");
НачатьТранзакцию();
Блокировка.Заблокировать();
// Выполнение операций с регистром
ЗафиксироватьТранзакцию();
Первое, на что стоит обратить внимание — это порядок вызова команд. В обсуждении прозвучало предложение устанавливать блокировку до начала транзакции. Разберем, почему это невозможно. Управляемые блокировки в 1С жестко привязаны к контексту транзакции. Если вызвать метод Заблокировать() вне транзакции, система выдаст ошибку, так как блокировка должна сниматься автоматически при завершении транзакции (фиксации или отмене). Поэтому правильная последовательность всегда: НачатьТранзакцию() -> Заблокировать() -> ЗафиксироватьТранзакцию().
Проанализируем строку Блокировка.Добавить("РегистрСведений.ТаблицыГруппДоступа"). В данном случае не указано ни одного пространства значений (фильтра). Это означает, что система пытается установить исключительную блокировку на весь регистр целиком.
Даже если регистр пуст, для менеджера блокировок 1С он является ресурсом. Если в этот момент другой сеанс (например, фоновое задание) читает данные из этого регистра в своей транзакции, он удерживает разделяемую (Shared) блокировку. Ваша попытка получить исключительную блокировку будет поставлена в очередь. Внешне это выглядит как «зависание» на строке Блокировка.Заблокировать().
Регистр ТаблицыГруппДоступа входит в состав подсистемы управления доступом БСП. В типовых конфигурациях (БП, ЗУП, ERP, БП ЖКХ) постоянно работают фоновые задания, такие как:
Эти задания могут инициировать длительные транзакции, в которых происходит чтение таблиц групп доступа. Поскольку обновление данных регистра требует исключительных прав, любой активный процесс чтения заблокирует вашу попытку обновления.
Иногда причина кроется глубже — на уровне кластера или СУБД (MS SQL Server, PostgreSQL). Рассмотрим несколько сценариев:
Repeatable Read блокируют гораздо большие диапазоны данных, чем управляемые блокировки.Чтобы решить проблему «зависания», выполним следующие действия:
Перед запуском процедур обновления данных, особенно если это касается прав доступа, необходимо временно отключить фоновые задания. Это можно сделать через консоль администрирования кластера или встроенную обработку «Регламентные и фоновые задания». Это гарантирует, что системные процессы не «перехватят» блокировку в самый ответственный момент.
Воспользуемся консолью администрирования кластера 1С. Разберем алгоритм действий:
Если визуально определить причину не удается, настроим сбор событий Технологического журнала. Нам интересны события TLOCK (установка блокировки) и TTIMEOUT (превышение времени ожидания). Проанализировав файл лога, мы увидим точное имя ресурса и номер сеанса-виновника.
Пример настройки logcfg.xml для поиска виновника:
<event query="e.type == 'TLOCK' | e.type == 'TTIMEOUT'">
<property name="all"/>
</event>
Если задача стоит просто очистить регистр, можно рассмотреть альтернативные методы, которые менее требовательны к блокировкам всего ресурса. Однако, если вы используете типовой код из модуля ОбновитьДанныеРегистра(), лучше обеспечить «чистую» среду для его выполнения.
Рассмотрим рекомендации по монопольному доступу. При выполнении критичных обновлений информационной базы полезно устанавливать блокировку установки соединений:
Зависание на пустом регистре — это классический симптом очереди блокировок. Несмотря на отсутствие записей в таблице, сам объект «РегистрСведений» является разделяемым ресурсом. Основной путь решения — исключение параллельных процессов (фоновых заданий) и проверка наличия зависших транзакций в кластере 1С или СУБД. Помните, что управляемые блокировки эффективны только тогда, когда они накладываются на конкретные измерения, а блокировка «всего регистра» должна применяться крайне осторожно и только в отсутствие других пользователей в системе.