При автоматизации крупных агропромышленных холдингов технические специалисты часто сталкиваются со спецификой сельскохозяйственного учета. Одной из наиболее сложных задач является закрытие года. В растениеводстве и животноводстве производственный цикл носит затяжной характер, из-за чего в течение всего календарного года затраты аккумулируются на счетах косвенных расходов (25 и 26), а в декабре происходит их глобальное распределение на затраты основного производства (счет 20).
В результате этой операции в информационной базе 1С:Бухгалтерия предприятия Агрокомплекс (БП) формируются «мега-документы» закрытия месяца, содержащие сотни тысяч бухгалтерских проводок (вплоть до 400 000 и более в одном документе). Попытка передать такой документ через стандартный механизм синхронизации данных (например, на базе формата EnterpriseData) в центральную базу 1С:Управление холдингом (УХ) приводит к полной остановке обмена, зависанию рабочих процессов и блокировке передачи другой оперативной информации на недели или даже месяцы.
В этой статье мы подробно проанализируем технические причины возникновения этой проблемы и рассмотрим эффективные архитектурные и системные решения, которые позволят оптимизировать этот процесс.
Прежде чем переходить к решениям, выясним первопричину сбоя на техническом уровне кластера 1С и СУБД:
rphost. Процесс либо принудительно перезапускается операционной системой по превышению лимитов, либо уходит в бесконечный своп (swap).Хозрасчетный, парализуя работу остальных пользователей и блокируя другие сессии обмена.Рассмотрим пошагово методы борьбы с этой проблемой — от простых организационных мер до глубокой переработки архитектуры интеграции.
Проанализируем методологическую необходимость передачи детальных данных. Центральной базе 1С:Управление холдингом, которая используется для консолидации и управленческой отчетности, чаще всего не требуется субконто-детализация первичных затрат каждого отдельного поля или единицы техники. Ей важен итоговый финансовый результат.
Для минимизации объема данных мы можем написать алгоритм свертки проводок на стороне источника (БП) перед отправкой. Вместо 400 000 детальных записей мы сгруппируем их по ключевым разрезам аналитики (Счет Дт/Кт, Субконто, Подразделение) и просуммируем.
Посмотрим на пример запроса, который позволяет выполнить группировку движений мега-документа перед отправкой в приемник:
// Пример запроса для свертки проводок перед выгрузкой
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйДвижения.СчетДт КАК СчетДт,
| ХозрасчетныйДвижения.СчетКт КАК СчетКт,
| ХозрасчетныйДвижения.СубконтоДт1 КАК СубконтоДт1,
| ХозрасчетныйДвижения.СубконтоКт1 КАК СубконтоКт1,
| ХозрасчетныйДвижения.ПодразделениеДт КАК ПодразделениеДт,
| ХозрасчетныйДвижения.ПодразделениеКт КАК ПодразделениеКт,
| СУММА(ХозрасчетныйДвижения.Сумма) КАК Сумма
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(&НачалоПериода, &КонецПериода, Регистратор = &Документ) КАК ХозрасчетныйДвижения
|
|СГРУППИРОВАТЬ ПО
| ХозрасчетныйДвижения.СчетДт,
| ХозрасчетныйДвижения.СчетКт,
| ХозрасчетныйДвижения.СубконтоДт1,
| ХозрасчетныйДвижения.СубконтоКт1,
| ХозрасчетныйДвижения.ПодразделениеДт,
| ХозрасчетныйДвижения.ПодразделениеКт";
Запрос.УстановитьПараметр("Документ", СсылкаНаМегаДокумент);
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(СсылкаНаМегаДокумент.Дата));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(СсылкаНаМегаДокумент.Дата));
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Использование этого метода позволяет сократить объем выгружаемых проводок на 95–98% без потери методологической точности в базе-приемнике. Вместо сотен тысяч строк мы передаем компактную таблицу из 2 000–5 000 записей, которая обрабатывается стандартным механизмом за секунды.
Если методология учета требует сохранения абсолютной детализации всех проводок, мы можем применить паттерн дробления данных. Сверхкрупный документ в БП необходимо автоматически разделить на несколько документов меньшего размера непосредственно перед регистрацией к обмену.
Разберем по шагам логику реализации этого механизма:
Рассмотрим пример кода на встроенном языке 1С, реализующий логику порционного создания документов:
// Алгоритм разбиения таблицы проводок мега-документа на порции
РазмерПорции = 10000;
ВсегоСтрок = ТаблицаПроводок.Количество();
НомерПорции = 1;
Пока (НомерПорции - 1) * РазмерПорции < ВсегоСтрок Цикл
НовыйДокумент = Документы.ОперацияБух.СоздатьДокумент();
НовыйДокумент.Дата = ИсходныйДокумент.Дата;
НовыйДокумент.Организация = ИсходныйДокумент.Организация;
НовыйДокумент.Содержание = "Порция №" + Строка(НомерПорции) + " распределения затрат за год";
// Заполняем движения по регистру Хозрасчетный для текущей порции
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
ДвиженияХозрасчетный = НовыйДокумент.Движения.Хозрасчетный;
НачальныйИндекс = (НомерПорции - 1) * РазмерПорции;
КонечныйИндекс = Мин(НомерПорции * РазмерПорции - 1, ВсегоСтрок - 1);
Для Индекс = НачальныйИндекс По КонечныйИндекс Цикл
СтрокаИсточника = ТаблицаПроводок[Индекс];
НоваяПроводка = ДвиженияХозрасчетный.Добавить();
ЗаполнитьЗначенияСвойств(НоваяПроводка, СтрокаИсточника);
НоваяПроводка.Период = ИсходныйДокумент.Дата;
НоваяПроводка.Организация = ИсходныйДокумент.Организация;
КонецЦикла;
ДвиженияХозрасчетный.Записать();
НомерПорции = НомерПорции + 1;
КонецЦикла;
Такие небольшие документы легко сериализуются платформой, передаются по очереди и проводятся в приемнике быстрыми транзакциями, не перегружая оперативную память сервера и не вызывая длительных блокировок СУБД.
По умолчанию в типовых конфигурациях используется один план обмена для всех типов данных. Это стратегическая ошибка при наличии сверхкрупных документов. Если в очереди обмена зависает один мега-документ, вся остальная оперативная информация (справочники, текущие реализации, платежные поручения) встает в очередь позади него.
Для исправления ситуации настроим два независимых канала обмена:
Если мы хотим полностью разгрузить сессию синхронизации, применим архитектурный паттерн «Регистр входящих сообщений»:
РегистрСведений.ВходящийБуферОбмена, где в реквизите с типом ХранилищеЗначения сохраняется переданный текст файла. Сессия обмена мгновенно закрывается, не дожидаясь разбора данных.Когда стандартный механизм EnterpriseData падает из-за нехватки памяти, рекомендуется отказаться от объектной выгрузки через XDTO. Вместо этого разработаем собственный HTTP-сервис, использующий низкоуровневые объекты платформы 1С:
ЗаписьXML для последовательной записи проводок прямо в поток файла на диске. Это исключает удержание сотен тысяч объектов в ОЗУ.ЧтениеXML, который позволяет читать файл последовательно шаг за шагом (потоковый парсинг), сразу записывая проводки порциями в базу данных через набор записей регистра бухгалтерии, минуя создание тяжелых документов в оперативной памяти.Если кардинально переписать архитектуру обмена прямо сейчас нет возможности, мы можем временно применить системные настройки для снижения вероятности аварийного завершения процесса синхронизации:
РазмерТранзакцииПриЗагрузке (установим значение от 100 до 500 объектов вместо значения по умолчанию 0). Это позволит СУБД периодически фиксировать транзакции, освобождая память и блокировки таблиц.rphost не перезапускался принудительно посреди обработки тяжелого пакета.Применение предложенных подходов гарантирует стабильную работу синхронизации даже при пиковых годовых нагрузках в крупных сельскохозяйственных холдингах.