При активной работе пользователей в информационных базах 1С часто возникает неприятная ситуация: в процессе фонового обмена данными (синхронизации) начинают активно записываться и проводиться документы. В этот момент пользователи, формирующие оперативные отчеты (например, оборотно-сальдовую ведомость), сталкиваются с так называемыми «скачущими» цифрами. Данные постоянно меняются, так как транзакции обмена выполняются параллельно с формированием отчетов. Это вызывает раздражение у клиентов и снижает доверие к системе.
В данной статье мы подробно разберем, как технически правильно зафиксировать момент выполнения фонового обмена, почему популярный способ с использованием констант-маркеров является опасным костылем, и как решить проблему нестабильных показателей в отчетах профессиональными методами платформы 1С:Предприятие и СУБД.
Рассмотрим решение, к которому часто прибегают начинающие разработчики (и которое применил автор исходного вопроса на форуме). Суть метода заключается в создании кастомной константы, например, ВыполняетсяФоновыйОбмен со значением типа Булево. Схема работы выглядит следующим образом:
Истина.Истина, вывод отчета блокируется с выводом предупреждения пользователю.Ложь.Выясним причину, почему этот метод считается крайне ненадежным (костылем). Если во время выполнения обмена произойдет критическая ошибка — например, аварийное завершение сеанса, выключение сервера, неперехваченное исключение в коде загрузки объектов или переполнение памяти — транзакция завершится аварийно. В этом случае код, сбрасывающий константу в значение Ложь, попросту не выполнится. Флаг заблокируется в значении Истина навсегда, и ни один пользователь не сможет сформировать отчет до тех пор, пока администратор вручную не сбросит значение этой константы. Использование конструкции Попытка...Исключение...КонецПопытки не решает проблему на 100%, так как существуют аппаратные и системные сбои, которые не перехватываются программным кодом 1С.
Давайте разберем по шагам, как решить эту задачу правильно и безопасно.
Платформа 1С:Предприятие предоставляет надежный встроенный механизм для работы с процессами — менеджер фоновых заданий. Этот способ полностью безопасен: состояние фонового задания контролируется самим кластером серверов 1С. Если процесс упадет или завершится с ошибкой, статус задания автоматически изменится, и ложных блокировок не произойдет.
Рассмотрим пример кода, который проверяет, активен ли процесс обмена в текущий момент:
Функция ВыполняетсяФоновыйОбменДанными() Экспорт
Отбор = Новый Структура;
Отбор.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);
// В зависимости от конфигурации, фоновые обмены могут запускаться
// через регламентные задания. Отфильтруем по имени метода или метаданным.
// Например, для БСП это может быть метод "ОбменДаннымиСервер.ВыполнитьОбменДанными"
ВсеАктивныеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор);
Для Каждого Задание Из ВсеАктивныеЗадания Цикл
// Проверяем имя метода регламентного задания или имя самого задания
Если Найти(Задание.ИмяМетода, "ВыполнитьОбменДанными") > 0
Или Найти(Задание.Наименование, "Синхронизация") > 0 Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
Этот метод можно вызывать непосредственно перед формированием отчета в модуле формы или объекта. Если функция возвращает Истина, мы можем вежливо попросить пользователя подождать завершения синхронизации.
Если вы работаете в современной конфигурации, разработанной на управляемых формах (например, БСП 2.x или 3.x), то в системе уже заложены механизмы отслеживания состояния синхронизации. БСП хранит историю и текущие статусы в специализированных регистрах сведений.
Проанализируем структуру регистра сведений СостоянияОбменовДанными. В нем содержатся записи по каждому узлу плана обмена с фиксацией времени начала и окончания сессии обмена. Мы можем обратиться к этому регистру программным запросом:
Функция ПроверитьАктивностьОбменаБСП() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СостоянияОбменовДанными.УзелИнформационнойБазы КАК Узел,
| СостоянияОбменовДанными.РезультатВыполненияОбмена КАК Результат
|ИЗ
| РегистрСведений.СостоянияОбменовДанными КАК СостоянияОбменовДанными
|ГДЕ
| СостоянияОбменовДанными.РезультатВыполненияОбмена = ЗНАЧЕНИЕ(Перечисление.РезультатыВыполненияОбмена.Выполняется)";
РезультатЗапроса = Запрос.Выполнить();
Возврат Не РезультатЗапроса.Пустой();
КонецФункции
Использование этого метода позволяет точечно определять, идет ли обмен по конкретному узлу плана обмена (например, только с «Управлением торговлей»). Это дает возможность не блокировать пользователей полностью, а ограничивать формирование отчетов только по тем организациям или разделам учета, которые сейчас синхронизируются.
Зачастую блокировать отчеты пользователям вообще не требуется, если оптимизировать сам процесс проведения документов во время обмена. Причиной «скачущих» цифр и сильных зависаний при записи данных во время обмена является постоянный автоматический пересчет текущих итогов регистров.
Рассмотрим правильный алгоритм массовой загрузки данных, который сводит к минимуму нагрузку на таблицы итогов:
Хозрасчетный.Реализовать это в коде обработки обмена можно следующим образом:
// Перед началом транзакции загрузки
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеТекущихИтогов(Ложь);
// ... Код загрузки и проведения документов обмена ...
// После завершения загрузки
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеТекущихИтогов(Истина);
РегистрыБухгалтерии.Хозрасчетный.ПересчитатьИтоги();
Во время того, как итоги отключены, пользователи смогут формировать отчеты, но расчет будет идти по сохраненным итогам на конец предыдущих периодов (например, на конец прошлого месяца), что заблокирует появление хаотичных «минутных» искажений данных во время записи промежуточных документов обмена.
Если ваша база данных работает под управлением MS SQL Server в режиме управляемых блокировок 1С, существует фундаментальное системное решение проблемы «скачущих» отчетов. Эта проблема связана с грязным чтением (Dirty Read), когда транзакция чтения данных отчета видит промежуточные, еще не зафиксированные транзакцией обмена проводки.
Мы можем активировать на уровне СУБД технологию версионирования строк (Snapshot Isolation). Для этого администратору баз данных необходимо выполнить два SQL-запроса к рабочей базе:
ALTER DATABASE [Имя_Вашей_Базы] SET ALLOW_SNAPSHOT_ISOLATION ON;
ALTER DATABASE [Имя_Вашей_Базы] SET READ_COMMITTED_SNAPSHOT ON;
Что это дает на практике?
Использование этого подхода полностью избавляет от необходимости внедрять какие-либо костыли и ограничения в коде отчетов или конфигурации.
Мы рассмотрели различные варианты решения проблемы отображения нестабильных данных в отчетах во время фоновой синхронизации. Выбор метода зависит от архитектуры вашей системы: