Как перенести изменения из поврежденной базы 1С в архивную копию по журналу регистрации?

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

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

Анализ проблемы и выбор стратегии

Прежде всего, разберем, почему стандартные средства вроде планов обмена могут не подойти. Как отмечается в обсуждении, планы обмена нужно настраивать заранее. Если регистрация изменений не велась, мы не сможем задним числом узнать, какие именно объекты были изменены. Однако 1С по умолчанию ведет Журнал регистрации, в котором фиксируются все события создания и изменения объектов. Наша задача — извлечь список ссылок (GUID) этих объектов и перенести их состояние в живую базу.

Проанализируем основные шаги алгоритма восстановления:

  1. Извлечение списка уникальных идентификаторов (GUID) измененных объектов из поврежденной базы через ЖР.
  2. Выгрузка актуального состояния этих объектов из поврежденной базы в промежуточный файл.
  3. Загрузка данных в чистую архивную копию.
  4. Восстановление ссылочной целостности (битых ссылок).

Шаг 1: Извлечение данных из Журнала регистрации

Выясним, как программно получить список измененных объектов. Нам потребуется функция ВыгрузитьЖурналРегистрации(). Мы можем отфильтровать события по периоду (с момента создания архива до текущего момента) и по типу события (добавление или изменение данных).

Рассмотрим пример кода, который собирает ссылки на измененные объекты в таблицу значений:


// Создаем таблицу для хранения данных журнала
ТаблицаСобытий = Новый ТаблицаЗначений;
Фильтр = Новый Структура;
Фильтр.Вставить("ДатаНачала", НачалоДня(ТекущаяДата())); // Укажите время последнего архива
Фильтр.Вставить("Событие", "_$Data$_.Post, _$Data$_.Update, _$Data$_.New"); 

// Выгружаем журнал
ВыгрузитьЖурналРегистрации(ТаблицаСобытий, Фильтр);

// Формируем массив уникальных ссылок
МассивСсылок = Новый Массив;
Для Каждого СтрокаЖурнала Из ТаблицаСобытий Цикл
    Если ЗначениеЗаполнено(СтрокаЖурнала.Данные) Тогда
        МассивСсылок.Добавить(СтрокаЖурнала.Данные);
    КонецЕсли;
КонецЦикла;

Важный нюанс: Журнал регистрации в новых версиях платформы может храниться в формате SQLite (файл .lgf). Если база совсем не открывается в режиме "Предприятие", данные можно попытаться извлечь внешними утилитами чтения SQLite, так как файл журнала часто остается неповрежденным даже при разрушении основных таблиц базы данных .1CD.

Шаг 2: Использование обработки «Выгрузка и загрузка данных XML»

Посмотрим на практический совет из темы: совместить анализ ЖР со стандартной обработкой ВыгрузкаЗагрузкаДанныхXML.epf. Это наиболее надежный путь, так как типовая обработка корректно сериализует объекты со всеми табличными частями.

Разберем, как доработать стандартную обработку:

  1. Добавим на форму обработки возможность выбора периода анализа ЖР.
  2. В процедуре выгрузки добавим фильтр. Вместо выгрузки всех объектов метаданных, мы будем передавать массив ссылок, полученный на первом шаге, в параметр ПостроительОтчета или использовать метод УстановитьФильтр().

Проанализируем пример логики для фильтрации объектов в обработке:


// В коде обработки выгрузки, где происходит итерация по метаданным
Для Каждого ТипОбъекта Из ВыбранныеТипы Цикл
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ " + ТипОбъекта.ПолноеИмя() + " ГДЕ Ссылка В (&МассивИзЖР)";
    Запрос.УстановитьПараметр("МассивИзЖР", МассивСсылок);
    
    Результат = Запрос.Выполнить().Выгрузить();
    // Передаем результат в механизм сериализации XML
КонецЦикла;

Шаг 3: Проблема «битых» ссылок и восстановление целостности

При работе с «убитой» базой мы можем столкнуться с ситуацией Объект не обнаружен. Это происходит, когда запись в ЖР есть, а сама таблица объекта в базе повреждена. Выясним причину: это может быть следствием битых индексов файловой системы.

В этом случае рекомендуется:

Шаг 4: Версионирование как превентивная мера

Рассмотрим альтернативу, упомянутую в обсуждении — Версионирование объектов. В типовых конфигурациях (даже старых, таких как УТ 10.3) часто встроены подсистемы версионирования. Если бы оно было включено, восстановление данных прошло бы гораздо проще, так как версии объектов хранятся в отдельном регистре сведений ВерсииОбъектов. Каждый срез данных там — это готовый XML-пакет состояния объекта. Даже при полной потере основного документа, его данные можно восстановить из этого регистра.

Рекомендации по предотвращению аварий в файловых базах

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

  1. Переход на клиент-серверный вариант: Даже бесплатные версии SQL или PostgreSQL значительно стабильнее файлового режима .1CD при работе более 3-5 пользователей.
  2. Регулярное резервное копирование: Настройка выгрузки .dt или копирования файла базы каждые 2-3 часа в рабочее время.
  3. Исправление кривого кода: Как отмечено в сообщении 10, причиной блокировок часто является неоптимальный код (например, избыточные транзакции или чтение битых ссылок). Рекомендуется провести аудит кода, вызывающего конфликты блокировок.
  4. Настройка архивации журнала регистрации: Храните копии файлов .lgp/.lgf отдельно от основной базы. В критической ситуации именно они станут вашим «черным ящиком» для восстановления истории операций.

Используя предложенную методику «докатки» данных через XML на основе анализа журнала регистрации, вы сможете минимизировать потери данных и восстановить работоспособность системы в кратчайшие сроки.

← На главную