В практике разработки на платформе 1С:Предприятие 8 программисты часто сталкиваются с ситуацией, когда проверенный временем запрос внезапно начинает возвращать некорректные данные, а именно — удваивать или даже утраивать показатели. Рассмотрим типичный сценарий: есть оборотный регистр накопления, к которому обращается запрос для получения данных за определенный период. При использовании периодичности Авто данные двоятся, но если сменить периодичность на Регистратор, цифры становятся верными. Разберем подробно, почему это происходит и как правильно решить данную проблему.
Проанализируем пример запроса, который вызывает подозрения. В нем используется обращение к виртуальной таблице Обороты регистра накопления:
ВЫБРАТЬ
НашРегистрОбороты.Номенклатура,
НашРегистрОбороты.ХарактеристикаНоменклатуры,
НашРегистрОбороты.КоличествоОборот КАК Количество
ИЗ
РегистрНакопления.НашРегистр.Обороты(
&НачалоПериода,
&КонецПериода,
авто,
Параметр = &Параметр
И Категория = ЗНАЧЕНИЕ(Перечисление.Параметры.Параметр)
И Операция = ЗНАЧЕНИЕ(Перечисление.Параметры.Параметр1)) КАК НашРегистрОбороты
На первый взгляд, запрос составлен абсолютно корректно. Параметр периодичности авто является стандартным и часто используемым. Однако именно здесь кроется корень проблемы. Чтобы понять причину задвоения, нам нужно заглянуть "под капот" платформы и выяснить, как 1С работает с виртуальными таблицами.
Выясним, чем отличается поведение системы при разных настройках периодичности:
Если данные в таблицах итогов по какой-то причине "разошлись" с реальными движениями документов, мы получаем неверный результат. Задвоение — это классический признак того, что таблица итогов содержит "мусорные" записи или ошибки суммирования.
Проанализируем, почему в таблице итогов могут появиться лишние данные. Одной из частых причин является включенное свойство регистра «Разделение итогов». Этот механизм позволяет нескольким пользователям одновременно записывать данные в регистр по одним и тем же измерениям (например, по одной номенклатуре) без блокировок. Для этого система создает несколько физических записей в таблице итогов для одной и той же комбинации измерений. При чтении запросом 1С должна их суммировать. Если в структуре базы данных происходит сбой (аварийное завершение транзакции, ошибки СУБД), эти записи могут начать обрабатываться некорректно, выдавая кратный результат.
Также важно помнить, что итоги в регистрах накопления хранятся помесячно. Именно поэтому в нашем примере ошибка проявлялась только тогда, когда в период запроса попадал май (следующий месяц). Если "битым" оказался майский итог, то запрос за апрель будет верным, а запрос, включающий май, покажет задвоение.
Единственным правильным решением в данной ситуации является приведение таблиц итогов в соответствие с таблицами движений. Рассмотрим, как это сделать.
Это самый простой и надежный метод. Нам необходимо выполнить процедуру «Тестирование и исправление» (ТиИ):
Система полностью очистит таблицы итогов и сформирует их заново на основании записей в таблицах движений документов.
Иногда нет возможности выгнать всех пользователей из базы для монопольного доступа. В этом случае мы можем инициировать пересчет итогов программно с помощью встроенного языка. Для этого используется объект РегистрыНакопленияManager.
Рассмотрим пример кода для обработки:
// Выключаем использование итогов, что может привести к их очистке
РегистрыНакопления.НашРегистр.УстановитьИспользованиеИтогов(Ложь);
// Включаем обратно - система инициирует полный пересчет
РегистрыНакопления.НашРегистр.УстановитьИспользованиеИтогов(Истина);
// Можно также выполнить пересчет за конкретный период
РегистрыНакопления.НашРегистр.ПересчитатьИтоги(НачалоГода(ТекущаяДата()), КонецГода(ТекущаяДата()));
Важно: Программный пересчет в активной базе может вызвать серьезную нагрузку на сервер и СУБД. Рекомендуется выполнять такие процедуры в периоды минимальной активности пользователей.
Разберем, как избежать подобных проблем в будущем. Пересчет итогов не должен быть экстренной мерой. В крупных системах это обязательная регламентная процедура.
Подводя итог, отметим: если вы видите задвоение данных в виртуальных таблицах 1С, первым делом проверьте актуальность и целостность итогов. В 99% случаев Пересчет итогов решит проблему без необходимости менять логику самих запросов.