При работе с крупными информационными базами «1С:Бухгалтерия 3.0», где количество проводок по счету 41.01 исчисляется миллионами, стандартная операция включения партионного учета превращается в сложную техническую задачу. Попытка добавить субконто Партии через настройки параметров учета или напрямую в плане счетов часто приводит к ошибке "lock request time out period exceeded" (превышено время ожидания блокировки). Это происходит потому, что система пытается в рамках одной транзакции изменить структуру огромной таблицы регистра бухгалтерии и пересчитать итоги.
В этой статье мы подробно разберем, почему возникает эта проблема, и проанализируем пошаговые стратегии ее решения, используя инструменты платформы 1С и MS SQL Server.
Разберем ситуацию изнутри. Когда мы добавляем новое субконто на счет, платформа инициирует процесс реструктуризации таблиц базы данных. Основная нагрузка ложится на таблицу движений регистра бухгалтерии (обычно это _AccRg) и связанные с ней таблицы итогов. Если в таблице миллионы записей, SQL Server не может бесконечно блокировать отдельные строки и применяет механизм Lock Escalation (эскалация блокировок), блокируя таблицу целиком.
Даже если в базе «никого нет», конфликт могут вызвать:
Прежде чем приступать к изменениям, проанализируем настройки кластера серверов 1С. По умолчанию время ожидания блокировки составляет 20 секунд. Для реструктуризации миллионов строк этого катастрофически мало.
Выполним следующие действия:
5000 или более секунд.На стороне SQL Server также требуется провести подготовку. Основная проблема — рост лога транзакций и параллелизм, который может привести к взаимоблокировкам (deadlocks) процесса самого с собой.
Рассмотрим рекомендации по настройке SQL:
Simple. Это предотвратит бесконтрольный рост файла .LDF во время добавления субконто.Max Degree of Parallelism = 1. Это заставит SQL выполнять операцию в одном потоке, исключая ожидания типа CXPACKET.Пример команды для SQL Server Management Studio:
-- Перевод в Simple (замените MyBase на имя вашей базы)
ALTER DATABASE [MyBase] SET RECOVERY SIMPLE;
-- Отключение эскалации блокировок для таблицы регистра бухгалтерии
-- Имя таблицы нужно предварительно уточнить (например, через ПолучитьСтруктуруХраненияБазыДанных)
ALTER TABLE [_AccRg12345] SET (LOCK_ESCALATION = DISABLE);
Значительная часть времени при добавлении субконто тратится на пересчет итогов. Мы можем обмануть систему, временно отключив их. Выясним, как это сделать программно.
Создадим небольшую внешнюю обработку и выполним следующий код:
// Отключаем использование итогов, чтобы ускорить реструктуризацию
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Ложь);
// Также можно отключить текущие итоги
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеТекущихИтогов(Ложь);
После того как субконто будет добавлено через конфигуратор или настройки, итоги нужно будет включить обратно. Да, процесс включения итогов займет время, но это будет отдельная транзакция, которая не вызовет падения при изменении структуры метаданных.
Иногда ручное внесение изменений в план счетов через интерфейс "1С:Предприятие" вызывает более сложные цепочки блокировок, чем работа в конфигураторе. Проанализируем следующий алгоритм:
Партии).Если стандартные механизмы все равно выдают ошибку блокировки, применим «хитрый» метод: добавим субконто без автоматического заполнения, а затем заполним его данными вручную, используя технологические окна.
Рассмотрим по шагам:
Партии (например, документом оприходования или специально созданной «партией по умолчанию») порциями по 10 000 – 50 000 записей.Пример кода для порционной обработки данных:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 50000
| Хозрасчетный.Регистратор,
| Хозрасчетный.НомерСтроки
|ИЗ
| РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
|ГДЕ
| Хозрасчетный.СчетДт = &Счет41
| И Хозрасчетный.СубконтоДт1 = ЗНАЧЕНИЕ(Справочник.Партии.ПустаяСсылка)";
Запрос.УстановитьПараметр("Счет41", ПланыСчетов.Хозрасчетный.Товары);
Пока Истина Цикл
Результат = Запрос.Выполнить().Выгрузить();
Если Результат.Количество() = 0 Тогда Прервать; КонецЕсли;
НачатьТранзакцию();
Для Каждого Строка Из Результат Цикл
// Здесь логика замены/установки субконто
// Используем НаборЗаписей с фильтром по регистратору
КонецЦикла;
ЗафиксироватьТранзакцию();
КонецЦикла;
После успешного добавления субконто и завершения всех манипуляций, не забудьте вернуть систему в рабочее состояние:
Full (если это требуется по регламенту бэкапов).Таким образом, комбинируя настройку таймаутов кластера, оптимизацию SQL-сервера и программное управление итогами, мы можем успешно преодолеть конфликт блокировок даже на самых нагруженных базах «1С:Бухгалтерии 3.0».