В процессе администрирования и поддержки баз данных на платформе 1С:Предприятие 7.7 при работе с СУБД MS SQL Server специалисты иногда сталкиваются с крайне неприятным поведением системы. Документ, помеченный на удаление, неожиданно сохраняет свои движения по регистрам. Попытки провести или распровести его стандартными средствами не приносят результата. В порыве исправить ситуацию администраторы баз данных совершают критическую ошибку — удаляют движения проблемного документа напрямую через SQL-запросы. После этого возникает парадоксальная ситуация: в таблицах базы данных SQL физически нет никаких движений и остатков, но стандартные отчеты и запросы 1С продолжают упорно показывать наличие остатков по этим позициям.
В рамках этой статьи мы подробно разберем, почему возникает этот технический конфликт, как устроена архитектура таблиц регистров 1С 7.7 на MS SQL Server, и как исправить расхождение остатков без необходимости монопольного выгона пользователей из информационной базы.
Чтобы понять, откуда берется «фантомный» остаток, проанализируем структуру хранения данных оперативного учета платформы 1С:Предприятие 7.7 в СУБД SQL. Платформа разделяет физическое хранение любого регистра на две ключевые таблицы:
RAxxxx) — в этой таблице содержатся детальные записи о каждом факте прихода или расхода, совершенном документами-регистраторами. Каждая запись жестко привязана к определенному документу через его уникальный идентификатор.RGxxxx) — здесь хранятся предварительно рассчитанные остатки ресурсов в разрезе измерений (аналитики) регистра. Данные остатки рассчитываются на конец каждого месяца (периода) и на текущую Точку Актуальности (ТА).Рассмотрим подробнее механизм работы платформы при формировании отчетов. Когда мы строим отчет по движениям (например, ведомость движения товаров), платформа 1С обращается к таблице RAxxxx. Если вы удалили записи о движениях документа напрямую из SQL, то в этой таблице записей не окажется, и отчет покажет полное отсутствие движений.
Однако, когда отчет или запрос запрашивает текущие остатки, платформа в целях оптимизации быстродействия не пересчитывает все движения с начала времен. Вместо этого она берет уже готовые, предрассчитанные данные напрямую из таблицы итогов RGxxxx. Поскольку при ручном удалении движений из RAxxxx таблица RGxxxx осталась нетронутой, в ней зависли некорректные остатки. Таким образом, мы получаем опасное расхождение: движений нет, а остатки в отчетах есть.
Прежде чем исправлять последствия, разберем по шагам, почему изначально возникает ситуация, когда помеченный на удаление документ сохраняет проводки:
1SJOURN на «помечен на удаление», но транзакция по очистке таблиц регистров RAxxxx и RGxxxx была прервана или откатилась.Если на предприятии настроена непрерывная работа и нет возможности выгнать всех пользователей из базы для запуска монопольного «Тестирования и исправления» (которое полностью пересчитало бы итоги), отличным выходом станет использование специализированных внешних обработок.
Посмотрим на пример использования популярной обработки УстановкаТА.ert. Данная обработка позволяет управлять Точкой Актуальности (ТА) и выполнять выборочный пересчет итогов по конкретным регистрам без монопольного захвата базы. Алгоритм ее работы выглядит следующим образом:
RGxxxx на основе актуальных и физически существующих движений из таблицы RAxxxx. Все зависшие фантомные остатки будут корректно списаны и приведены в соответствие с реальностью.Чтобы избежать нарушения ссылочной целостности базы данных, настоятельно рекомендуется не прибегать к прямым SQL-запросам DELETE или TRUNCATE к таблицам RAxxxx без крайней необходимости. Безопаснее написать простую обработку на встроенном языке 1С, которая заставит саму платформу корректно очистить данные во всех связанных таблицах.
Рассмотрим пример кода, который возвращает «зависший» документ в исходное состояние и заново его распроводит по всем правилам бизнес-логики:
// Создаем объект для работы с документом
Док = СоздатьОбъект("Документ");
ВыбранныйДок = "Реализация"; // Укажите вид вашего документа
Если Док.НайтиДокумент(СсылкаНаПроблемныйДокумент) = 1 Тогда
// Шаг 1: Временно снимаем пометку удаления
Док.СнятьПометкуУдаления();
// Шаг 2: Принудительно делаем документ непроведенным
Док.СделатьНепроведенным();
// Шаг 3: Вызываем штатный метод очистки всех движений по регистрам
Док.ОчиститьДвижения();
// Шаг 4: Снова помечаем документ на удаление
Док.УстановитьПометкуУдаления();
Предупреждение("Документ успешно обработан. Движения корректно удалены из RA и RG!");КонецЕсли;
При таком подходе платформа выполнит все транзакции на уровне СУБД согласованно, гарантируя чистоту как в таблицах движений RAxxxx, так и в таблицах остатков RGxxxx.
Если объем регистра колоссален, а монопольный доступ получить невозможно, опытные администраторы баз данных прибегают к прямому пересчету итогов через T-SQL. Для этого пишется скрипт, выполняющий следующие действия:
RGxxxx для проблемного регистра с помощью команды TRUNCATE TABLE.RAxxxx заново рассчитываются остатки на конец каждого месяца исторического периода и записываются в RGxxxx.Важно: Этот метод требует глубокого понимания структуры метаданных конкретной конфигурации и файла словаря данных 1cv7.dd, так как имена таблиц и полей в SQL зашифрованы внутренними идентификаторами платформы (например, SP123, IDDOC и т.д.).
Чтобы минимизировать вероятность возникновения подобных «глюков» с регистрами в будущем, рекомендуется придерживаться нескольких простых правил обслуживания базы данных:
1С++, которая позволяет выполнять точечный пересчет итогов по выбранным регистрам.