Каждый практикующий специалист 1С рано или поздно сталкивается с загадочным поведением системы: при проведении расходного документа (например, Реализации товаров и услуг) программа выдает ошибку проведения («Отказ»), сообщая о нехватке свободных остатков или возникновении ложного резерва. При этом, если построить отчет по остаткам за один период — данные идеальные, но стоит сдвинуть границу отчета всего на один день — начинаются необъяснимые расхождения.
В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем архитектуру хранения итогов в СУБД на платформе «1С:Предприятие 8.3» и рассмотрим эффективные методы исправления ситуации на базах большого объема (более 15 ГБ) без запуска длительного процесса тестирования и исправления (ТИИ).
Рассмотрим классическую ситуацию. Пользователь проверяет остатки товаров отчетом «Товары организаций» за ровный период (например, с 01.11 по 30.11), чтобы получить конечный остаток на 01.12. В результате система выводит абсолютно корректные цифры, соответствующие реальному положению дел на складе. Однако стоит сформировать тот же отчет с небольшим сдвигом (например, со 02.11 по 31.12), как на те же самые позиции выводятся огромные отрицательные остатки или нереальные резервы, которых физически никогда не существовало.
Для того чтобы понять природу этой «чертовщины», нам необходимо заглянуть на уровень базы данных СУБД. В платформе 1С любой регистр накопления остатков состоит как минимум из двух связанных физических таблиц:
_AccumRg). В ней последовательно хранятся детальные записи, сделанные каждым документом-регистратором с указанием конкретной даты и времени._AccumRgT). Здесь платформа хранит предварительно рассчитанные и сгруппированные остатки на начало каждого месяца. Это сделано исключительно ради повышения производительности системы, чтобы при получении актуальных остатков 1С не приходилось заново пересчитывать миллионы строк движений с самого начала ведения учета.Когда мы строим отчет или проводим документ на «чистую» дату начала месяца (например, 01.12), оптимизатор запросов платформы обращается напрямую к таблице итогов _AccumRgT на эту дату. Если таблица итогов не повреждена, мы видим верный результат.
Однако, как только мы сдвигаем период хотя бы на один день (например, строим отчет со 02.11), алгоритм работы платформы кардинально меняется. Система выполняет следующие действия:
_AccumRgT на начало ближайшего месяца._AccumRg за «выпавшие» или «сдвинутые» дни.Если в процессе эксплуатации базы данных произошел сбой и таблица итогов оказалась повреждена («побилась»), а таблица движений при этом осталась абсолютно корректной, то при динамическом расчете за произвольный период пользователь гарантированно получает ложные (часто абсурдные) цифры. При проведении расходных документов система выполняет аналогичные динамические расчеты, видит «виртуальную» нехватку или несуществующий резерв и блокирует проведение документа.
Давайте проанализируем, почему происходит рассинхронизация таблиц итогов и движений. В крупных базах (особенно объемом более 15 ГБ) при интенсивной многопользовательской работе это происходит по нескольким основным причинам:
rphost), пропадает электропитание сервера СУБД или у пользователя принудительно закрывается сеанс, транзакция может записаться частично. Движения в основную таблицу _AccumRg успевают записаться, а регламентное обновление таблицы остатков _AccumRgT прерывается.ТоварыОрганизаций и РезервыТоваровОрганизаций, по умолчанию включен режим разделения итогов. На уровне СУБД это создает дополнительные строки со специальным системным разделителем (поле _Splitter), чтобы пользователи могли одновременно проводить документы по одним и тем же аналитикам без взаимных блокировок. В некоторых версиях платформы (включая ветку 8.3.15) зафиксированы технологические ошибки, из-за которых при высокой параллельной нагрузке данные разделителей консолидировались некорректно, приводя к ложным отрицательным остаткам.Запуск полного тестирования и исправления (ТИИ) через Конфигуратор на базах объемом от 15 ГБ крайне неэффективен. Процедура требует монопольного доступа, останавливает работу всей компании и может занимать долгие часы. Рассмотрим три точечных и быстрых способа исправления поврежденных итогов.
Этот способ является наиболее безопасным и доступен непосредственно в режиме «1С:Предприятие» под правами администратора. Нам не потребуется монопольный доступ ко всей базе данных.
Товары организаций и Резервы товаров организаций).Пересчет только по двум проблемным регистрам займет всего несколько минут вместо многочасового ожидания завершения полного ТИИ всей информационной базы.
Если нам необходимо максимально быстро решить проблему программным путем (например, из внешней обработки), мы можем применить классический прием сброса итогов. При отключении использования итогов по регистру платформа 1С физически очищает соответствующую таблицу _AccumRgT в СУБД, а при последующем включении — полностью пересоздает и пересчитывает ее на основе актуальной и неповрежденной таблицы движений _AccumRg.
Для реализации этого метода напишем и запустим следующий код во внешней обработке:
// Отключаем использование итогов для регистра "Товары организаций"
РегистрыНакопления.ТоварыОрганизаций.УстановитьИспользованиеИтогов(Ложь);
// Включаем использование итогов обратно - запускается полный автоматический пересчет
РегистрыНакопления.ТоварыОрганизаций.УстановитьИспользованиеИтогов(Истина);
// Выполняем аналогичную процедуру для регистра "Резервы товаров организаций"
РегистрыНакопления.РезервыТоваровОрганизаций.УстановитьИспользованиеИтогов(Ложь);
РегистрыНакопления.РезервыТоваровОрганизаций.УстановитьИспользованиеИтогов(Истина);
Сообщить("Пересчет итогов по проблемным регистрам успешно завершен!");
Важно: Выполнение данного программного кода требует монопольного доступа к конкретным регистрам накопления, поэтому его рекомендуется запускать в периоды минимальной активности пользователей или во внерабочее время.
Данный метод предназначен исключительно для опытных администраторов баз данных и применим только в клиент-серверном варианте работы системы. Он позволяет сэкономить время на операциях удаления строк средствами самой платформы 1С.
ПолучитьСтруктуруХраненияБазыДанных()).TRUNCATE TABLE (например, TRUNCATE TABLE _AccumRgT12345). Команда TRUNCATE работает мгновенно, так как она не записывает лог транзакций на каждую удаляемую строку.Проанализировав все три метода, мы можем сделать вывод, что регулярный контроль состояния итогов и использование точечных инструментов их пересчета позволяют полностью исключить возникновение ложных отрицательных остатков и резервов, обеспечивая стабильную и быструю работу конфигураций семейства «1С:ERP» и «1С:Управление торговлей».