Почему при создании начального образа РИБ смещается регистратор в движениях и как это исправить?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

При формировании начального образа подчиненного узла распределенной информационной базы (РИБ) разработчики и администраторы иногда сталкиваются с критической ошибкой: в созданной подчиненной базе данные документов и их движения рассинхронизируются. Например, в регистре накопления или сведений записи физически присутствуют, но отбор по регистратору указывает на один документ, а в самих строках движений фигурирует ссылка на совершенно другой (обычно предыдущий по выборке) документ. В результате стандартное тестирование и исправление выдает ошибки некорректных регистраторов, нарушается целостность учета, а при записи в подчиненной базе могут возникать ошибки нарушения уникальности индексов.

Разберем детально механизм возникновения данной проблемы и рассмотрим все проверенные способы ее устранения.

Анализ причин: особенности платформы и буферизация

Выясним причину такого некорректного поведения. Чаще всего сбой проявляется в версиях платформы линейки 8.3.9 (например, 8.3.9.1850). В этой ветке разработчиками платформы был внедрен внутренний механизм оптимизации выборки наборов записей регистров для ускорения процедуры формирования начального образа.

При работе в клиент-серверном режиме (SQL) этот механизм содержит ошибку управления внутренним буфером: при последовательном переборе документов буфер чтения набора записей перед следующей итерацией не сбрасывается полностью. В момент отправки данных значение Отбор.Регистратор.Значение набора записей уже указывает на текущий выгружаемый документ, но внутри самого набора в коллекции строк остаются данные предыдущего документа. Проанализируем это состояние: если проверить свойства объекта в точке останова обработчика обмена, можно увидеть явное несоответствие между значением отбора набора и реквизитом Регистратор в первой строке набора.

Примечательно, что в файловом варианте информационной базы данный серверный конвейер оптимизации не задействуется, и ошибка не воспроизводится.

Также дополнительным фактором сбоя может выступать наличие не уникальных движений в таблицах исходной базы (повреждение агрегатных таблиц или индексов СУБД), из-за чего при выгрузке на SQL-сервере вылетает исключение дублирования ключей.

Решение 1. Программный обход через перечитывание наборов записей

Если требуется создать начальный образ на текущей версии конфигурации и платформы без остановки сервера, рассмотрим программный способ исправления. В типовых и доработанных конфигурациях обработка выгрузки выполняется в общем модуле в событии отправки данных подчиненному узлу. Мы можем принудительно перечитать набор записей непосредственно перед сериализацией.

Посмотрим на пример реализации в процедуре-обработчике события:


Процедура ПриОтправкеДанныхПодчиненномуСобытие(Источник, ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза) Экспорт

    Если СозданиеНачальногоОбраза Тогда
        ИмяБазовогоТипа = ОбщегоНазначения.ИмяБазовогоТипаПоОбъектуМетаданных(ЭлементДанных.Метаданные);
        
        Если ИмяБазовогоТипа = ОбщегоНазначения.ИмяТипаРегистрыСведений
            ИЛИ ИмяБазовогоТипа = ОбщегоНазначения.ИмяТипаРегистрыНакопления
            ИЛИ ИмяБазовогоТипа = ОбщегоНазначения.ИмяТипаРегистрыБухгалтерии
            ИЛИ ИмяБазовогоТипа = ОбщегоНазначения.ИмяТипаРегистрыРасчета Тогда
            
            // Сбрасываем некорректный платформенный буфер принудительным чтением из базы
            ЭлементДанных.Прочитать();
            
        КонецЕсли;
    КонецЕсли;

    ПриОтправкеДанныхПодчиненному(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза, Источник);

КонецПроцедуры

Вызов метода Прочитать() обращается напрямую к базе данных и заполняет набор актуальными строками текущего регистратора. Данное решение полностью ликвидирует смещение данных, однако увеличивает общее время создания начального образа на больших объемах информации.

Решение 2. Создание начального образа через файловый режим

Поскольку ошибка буферизации платформы проявляется только в клиент-серверном режиме работы, самым надежным и быстрым вариантом без модификации конфигурации является выгрузка через файловую версию базы. Разберем этот алгоритм по шагам:

  1. Создаем резервную копию центральной информационной базы, выгрузив ее в файл с расширением .dt.
  2. Создаем чистую файловую базу на локальном диске или быстром накопителе и загружаем в нее полученный файл .dt.
  3. В файловой базе запускаем сеанс и выполняем стандартное создание начального образа для нужного подчиненного узла РИБ. Так как в файловом режиме оптимизированный сбойный алгоритм сервера не задействован, все наборы записей сформируются со строго корректными регистраторами.
  4. Полученный начальный образ подчиненного узла (файловый 1Cv8.1CD) переносим на рабочий сервер: загружаем его в новую базу SQL через выгрузку/загрузку .dt либо средствами платформы.
  5. Подключаем узел к регулярному обмену. Все последующие пакеты синхронизации через XML-файлы будут передаваться штатно без искажения движений.

Решение 3. Обновление или даунгрейд платформы 1С:Предприятие

Если создание начального образа требуется выполнять регулярно в автоматическом режиме, рекомендуется устранить саму первопричину на уровне платформы:

  1. Обновление на линейку 8.3.10 и выше. В ветках платформы начиная с 8.3.10 серверный алгоритм сериализации наборов записей при формировании РИБ был переработан разработчиками 1С, и дефект с удержанием предыдущего регистратора в буфере исправлен.
  2. Откат на стабильную ветку 8.3.8 (например, 8.3.8.2137) или 8.3.6. Если конфигурация поддерживает работу на более ранних релизах, можно временно перевести базу на эти версии для генерации узла, так как в них этот оптимизационный механизм еще не использовался.

Решение 4. Создание пустого образа с последующей инициализацией через обмен

Рассмотрим альтернативный способ развертывания распределенной базы, исключающий выгрузку огромного массива движений через процедуру создания образа:

  1. Создаем начальный образ подчиненного узла конфигурации без данных либо с отбором, отсекающим старые движения.
  2. После инициализации подчиненной базы в главном узле принудительно регистрируем все необходимые документы и регистры с помощью метода ПланыОбмена.ЗарегистрироватьИзменения().
  3. Выполняем штатный сеанс обмена данными. При стандартном формировании XML-сообщения обмена механизм пакетного кэширования начального образа не участвует, поэтому все наборы движений выгружаются корректно.

Решение 5. Устранение неуникальных движений и проверка целостности

В ситуациях, когда создание образа аварийно прерывается ошибками СУБД о нарушении уникальности индексов, необходимо устранить расхождения в исходной базе:

  1. Запускаем операцию Тестирование и исправление в центральной базе с обязательным выбором пункта Пересчет итогов. Это устраняет расхождения между физическими записями регистров и таблицами итогов.
  2. Если в процессе выгрузки на SQL фиксируется конкретная таблица регистра, находим дублирующиеся строки запросом к регистратору и выполняем перепроведение проблемных документов.
  3. Выполняем дефрагментацию и реиндексацию таблиц базы данных средствами самой СУБД для исключения логических повреждений индексов.
← На главную