Как устранить конфликт блокировок из-за константы «НомерЗаданияКФормированиюДвиженийПоНДС» в 1С:КА 2 и ERP?

Программист 1С v8.3 (Управляемые формы) 1С:Комплексная автоматизация Налоговый учет IT и автоматизация бизнеса
← На главную

При активной работе пользователей в программах 1С:Комплексная автоматизация 2 или 1С:ERP Управление предприятием часто возникает неприятная ситуация: во время проведения обычных документов (таких как «Заказ клиента», «Реализация товаров и услуг», «Перемещение товаров» или при закрытии месяца) система аварийно завершает работу. На экран выводится критическая ошибка: «Конфликт блокировок при выполнении транзакции: Превышено максимальное время ожидания предоставления блокировки» с указанием на константу НомерЗаданияКФормированиюДвиженийПоНДС.

В этой статье мы подробно проанализируем, почему возникает данная техническая проблема, разберем архитектурные причины конфликта на уровне СУБД, а также рассмотрим по шагам все возможные способы её исправления как на уровне администрирования, так и на уровне разработки.

Почему возникает конфликт блокировок из-за этой константы?

Давайте разберем внутреннюю кухню распределения задач в ERP-решениях 1С. Константа НомерЗаданияКФормированиюДвиженийПоНДС выполняет роль глобального координатора или счетчика пакетов данных. Когда запускается процедура «Формирование движений по НДС» (особенно в многопоточном режиме при закрытии месяца), система делит весь массив документов на порции. Чтобы параллельные фоновые задания не обрабатывали одни и те же транзакции, система нумерует эти порции (задания), последовательно считывая и увеличивая значение этой константы.

Проблема кроется в следующих факторах:

  1. Эксклюзивность блокировки констант. С точки зрения платформы 1С и СУБД (MS SQL Server, PostgreSQL и др.), любая операция записи нового значения в константу накладывает на соответствующую запись в таблице базы данных монопольную (исключительную) блокировку. Пока транзакция одного пользователя (или одного фонового потока) полностью не завершится, ни один другой процесс не сможет изменить или даже прочитать эту константу в режиме управляемых блокировок.
  2. Высокая конкуренция потоков. Если одновременно несколько пользователей проводят первичные документы или система в несколько потоков рассчитывает НДС, все эти процессы выстраиваются в жесткую очередь к одной-единственной записи в таблице констант.
  3. Превышение таймаута ожидания. Стандартный лимит ожидания блокировки в платформе «1С:Предприятие» составляет 20 секунд. Если один из потоков выполняет тяжелую транзакцию (например, проводит документ с огромным количеством строк), другие потоки «висят» в очереди. Как только время ожидания превышает 20 секунд, выполнение прерывается с ошибкой.

Это классический пример нарушения стандартов разработки Фирмы 1С. Согласно официальной «Системе стандартов и методик разработки конфигураций», использовать константы для хранения оперативно меняющихся данных (счетчиков, очередей задач) категорически запрещено. Для этих целей должны применяться регистры сведений с включенным режимом управляемых блокировок.

Как определить, какой именно сеанс блокирует константу?

Перед тем как приступать к исправлению, выясним, как оперативно локализовать виновника блокировки в работающей базе данных. Проанализируем несколько доступных инструментов:

Способ 1: Использование консоли администрирования кластера серверов 1С
В утилите администрирования перейдите в ветку вашего информационного склада, откройте список «Сеансы». Добавьте в список колонки «Заблокировано СУБД» и «Захватил СУБД». Во время возникновения ошибки вы сможете увидеть, какой конкретно сеанс держит эксклюзивную блокировку на таблицу констант.

Способ 2: Настройка Технологического журнала (ТЖ)
Для детального логирования дедлоков и таймаутов мы можем настроить сбор событий DBMSSQL и TLOCK. Создайте файл logcfg.xml в каталоге конфигурирования платформы со следующим содержимым:


<config xmlns="http://v8.1c.ru/v8/tech-journal">
    <log location="C:\v8logs\locks" history="24">
        <event>
            <eq property="Name" value="TLOCK"/>
        </event>
        <event>
            <eq property="Name" value="TTIMEOUT"/>
        </event>
        <property name="all"/>
    </log>
</config>

Анализ полученных логов позволит с точностью до секунды и строки кода определить, какая процедура инициировала длительную транзакцию.

Способы исправления ошибки и оптимизации системы

Разберем по шагам практические методы решения проблемы, начиная с простых административных настроек и заканчивая программным обходом.

1. Корректировка параметров порционного расчета НДС

В конфигурациях ERP и КА предусмотрена специальная настройка, регулирующая размер пакетов при расчете НДС. Перейдите в раздел администрирования закрытия месяца и найдите параметры этапа «Формирование движений по НДС». По умолчанию параметр «Количество заданий для порционного расчета НДС» равен 100. Изменение этого значения в меньшую сторону снизит размер транзакций и нагрузку на СУБД, а увеличение — сократит общее число транзакций записи в константу. Экспериментальным путем подберите оптимальный баланс под ваше серверное оборудование.

2. Использование механизма блокировки закрытых периодов

Очень часто фоновые задания генерации движений НДС запускаются из-за того, что пользователи случайно перепроводят или изменяют документы в прошлых (уже закрытых) периодах. Настоятельно рекомендуем включить жесткую «Дату запрета изменения данных» для всех пользователей, кроме администраторов. Это избавит систему от избыточной генерации фоновых задач по историческим данным и разгрузит общую константу-координатор.

3. Перенос тяжелых регламентных операций на внерабочее время

Параллельный запуск расчета себестоимости, закрытия месяца и активного ввода первичных документов (отгрузок, оплат, возвратов) практически гарантированно приведет к дедлокам на стыке констант и регистров сведений. Настройте расписание регламентных заданий так, чтобы все ресурсоемкие операции выполнялись ночью или в периоды минимальной активности пользователей.

4. Временное увеличение времени ожидания блокировки

Если проблему нужно устранить немедленно, чтобы пользователи могли продолжить работу, мы можем временно увеличить системный таймаут ожидания блокировок с стандартных 20 до 40–60 секунд. Сделать это можно в Конфигураторе через меню Администрирование — Параметры информационной базы — Время ожидания блокировки данных. Это даст процессам дополнительное время дождаться своей очереди, хотя и может субъективно замедлить отклик интерфейса при высокой нагрузке.

5. Установка официальных исправлений (патчей) 1С

Так как данная проблема имеет массовый характер и признана разработчиками фирмы 1С как несовершенство архитектуры, периодически выпускаются официальные патчи (исправления). В последних релизах ERP и КА разработчики постепенно уходят от хранения оперативных очередей в константах. Регулярно проверяйте и устанавливайте обновления конфигурации и платформы.

Рекомендации для разработчиков: как переписать алгоритм

Если вы работаете на нетиповой или сильно измененной конфигурации и имеете возможность вносить изменения в код, то лучшим решением будет отказ от константы. Перенесите хранение счетчика заданий в непериодический регистр сведений (например, создав регистр ОчередьЗаданийНДС) с включенным режимом управляемых блокировок.

Рассмотрим пример кода, как безопасно инкрементировать значение счетчика в транзакции с использованием механизма управляемых блокировок платформы 1С:


НачатьТранзакцию();
Попытка
    // Инициализируем управляемую блокировку для нашего регистра-счетчика
    Блокировка = Новый БлокировкаДанных;
    ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.СчетчикиЗаданийНДС");
    ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
    
    // Блокируем конкретный ключ (например, имя счетчика)
    ЭлементБлокировки.УстановитьЗначение("ИмяСчетчика", "ФормированиеДвиженийПоНДС");
    Блокировка.Заблокировать();
    
    // Читаем текущее значение из регистра
    Отбор = Новый Структура("ИмяСчетчика", "ФормированиеДвиженийПоНДС");
    ТекущееЗначение = РегистрыСведений.СчетчикиЗаданийНДС.ПолучитьПоследнее(,, Отбор).Значение;
    
    // Записываем инкрементированное значение
    МенеджерЗаписи = РегистрыСведений.СчетчикиЗаданийНДС.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.ИмяСчетчика = "ФормированиеДвиженийПоНДС";
    МенеджерЗаписи.Значение = ТекущееЗначение + 1;
    МенеджерЗаписи.Записать(Истина);
    
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ВызватьИсключение "Не удалось выделить номер задания из-за конфликта блокировок: " + ОписаниеОшибки();
КонецПопытки;

Использование регистра сведений с точечной блокировкой по измерению (в отличие от блокировки всей таблицы констант) позволяет значительно повысить параллельность работы пользователей и полностью избавиться от зависаний системы при формировании движений по НДС.

← На главную