Как восстановить базу 1С 7.7 Торговля и Склад после аварийного отключения питания и сбоя DBF

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

Аварийное отключение электроэнергии на сервере — один из самых опасных сценариев для файловых баз данных формата DBF, используемых в платформе 1С:Предприятие 7.7. Внезапная остановка системы, особенно при некорректной работе источников бесперебойного питания (ИБП) или дисковых массивов RAID без батарейной защиты (BBU), приводит к рассинхронизации таблиц, разрушению индексов и потере транзакционных данных.

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

Причины появления текстового «мусора» в полях таблиц DBF

При анализе поврежденного файла 1SJOURN.dbf (системный журнал документов) после аварийного перезапуска сервера часто обнаруживается, что числовые поля, поля дат и служебные признаки заполнены обрывками обычного текста (например, «еко», «рректные», «записи», «тега»). Выясним причину этого явления.

Современные операционные системы и аппаратные RAID-контроллеры используют технологию отложенной записи (Write-Back Cache). Данные, которые 1С отправляет на запись, сначала попадают в быстрый кэш оперативной памяти (системный кэш ОС или кэш RAID-контроллера) и лишь спустя некоторое время физически сбрасываются на жесткие диски. Если в момент нахождения данных в кэше происходит мгновенное обесточивание сервера, то страницы памяти перемешиваются.

При последующем запуске операционная система пытается восстановить поврежденную файловую систему (например, NTFS) с помощью утилит типа CHKDSK. В процессе восстановления утилита может записать фрагменты системных логов, текстовых файлов или дампов памяти (где содержались логи работы ККТ и ОФД со словами «некорректные записи тега») непосредственно в физические секторы, выделенные под таблицы 1С. В результате заголовки и записи DBF-файлов оказываются перезаписаны случайным «мусором».

Почему в Журнале регистрации чеки видны, а в самой базе данных — нет?

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

Журнал регистрации в 1С 7.7 представляет собой простой текстовый файл 1cv7.mlg, расположенный в каталоге SysLog. Запись в него производится последовательно методом добавления строк в режиме реального времени. Поскольку текстовый файл пишется напрямую и не требует сложных транзакционных блокировок нескольких таблиц, запись о проведении чека ККМ успела физически сохраниться на диске до отключения питания.

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

  1. 1SJOURN.dbf — общая информация о документе (дата, время, номер, проведен/помечен на удаление).
  2. DH* (например, DH1345.dbf) — таблица шапки документа (клиент, склад, касса, сумма).
  3. DT* (например, DT1345.dbf) — таблица табличной части документа (номенклатура, количество, цена).
  4. Таблицы движений регистров (RA* и RG*).

В момент сбоя транзакция по записи этих таблиц осталась в энергозависимом кэше диска и не была завершена. Документ физически исчез из таблиц СУБД, хотя запись в текстовом логе ЖР о его создании осталась.

Что означает ошибка «Неверный признак удаленности записи»?

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

Каждая запись (строка) в файле формата DBF начинается со специального служебного байта (маркера удаления). Этот байт может принимать только два валидных значения:

Если из-за сбоя файловой системы в этот первый байт записывается любой другой символ (буква, цифра, знак препинания из системного мусора), платформа 1С теряет способность определить статус строки и классифицирует это как нарушение физической целостности таблицы DBF.

Методика ручного восстановления базы данных без запуска долгого ТиИ

Штатная процедура «Тестирование и исправление» (ТиИ) в Конфигураторе на больших базах данных может выполняться часами, что неприемлемо при жестких временных рамках (например, когда магазин должен открыться через несколько часов). Более того, при выборе опции «Удалять битые объекты» ТиИ может безвозвратно затереть важные логические связи.

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

  1. Создание резервной копии: Перед любыми манипуляциями обязательно копируем всю папку с базой данных в безопасное место.
  2. Использование DBF-редактора: Открываем поврежденный файл (например, 1SJOURN.dbf) в специализированном DBF-редакторе (DBF Commander, DBFNavigator). Поврежденные записи обычно находятся в самом конце таблицы.
  3. Очистка битого хвоста: Находим строки, содержащие текстовый мусор в числовых полях, выделяем их и удаляем. После удаления поврежденных строк выполняем команду PACK (сжатие таблицы), чтобы физически переписать заголовок файла с корректным числом оставшихся записей.
  4. Реконструкция журнала документов: Если таблицы шапок (DH*) и табличных частей (DT*) документов уцелели, мы можем восстановить записи в 1SJOURN.dbf программно. Для этого используем внешние обработки автоматического воссоздания журнала (например, утилиту restjourn.ert), которая сканирует таблицы документов и генерирует для них корректные строки в системном журнале.
  5. Удаление индексных файлов: Полностью удаляем все файлы с расширением *.CDX из каталога базы данных. При первом запуске 1С в монопольном режиме система автоматически переиндексирует базу данных, создав чистые и актуальные индексы.
  6. Пересчет итогов: Чтобы восстановить корректные остатки товаров на складах и взаиморасчеты, заходим в Конфигуратор и запускаем операцию «Пересчет итогов» (или используем программный вызов ПересчетИтогов()).

Восстановление утерянных чеков на основе данных ОФД

Если часть чеков ККМ безвозвратно утеряна в базе 1С, но физически они прошли через фискальный накопитель и были отправлены оператору фискальных данных (ОФД), мы можем восстановить их. Самый простой путь — выгрузить чеки из личного кабинета ОФД в формате JSON и загрузить их обратно в 1С.

Проанализируем структуру JSON-документа ОФД и сопоставим его ключевые теги с реквизитами документов в 1С:

Рассмотрим пример программного разбора JSON-файла ОФД в среде 1С:Предприятие 7.7 с использованием стандартного системного объекта ScriptControl. Этот метод позволяет автоматизировать процесс создания утерянных документов без ручного ввода кассирами.


// Процедура автоматического импорта чека из JSON-файла ОФД
Процедура ЗагрузитьЧекИзJSON(ПутьКФайлу)
    
    // Создаем объект для работы со скриптами JScript
    JS = СоздатьОбъект("MSScriptControl.ScriptControl");
    JS.Language = "JScript";
    
    // Добавляем вспомогательные функции для доступа к свойствам объектов JS
    JS.AddCode("function getProp(obj, key) { return obj[key]; }");
    JS.AddCode("function getArrayElem(arr, idx) { return arr[idx]; }");
    JS.AddCode("function getArrayLength(arr) { return arr.length; }");
    
    // Читаем содержимое JSON-файла
    ТекстДокумента = СоздатьОбъект("Текст");
    ТекстДокумента.Открыть(ПутьКФайлу);
    СтрокаJSON = "";
    Для Ном = 1 По ТекстДокумента.КоличествоСтрок() Цикл
        СтрокаJSON = СтрокаJSON + ТекстДокумента.ПолучитьСтроку(Ном);
    КонецЦикла;
    
    Попытка
        // Парсим строку JSON в объект JavaScript
        ЧекJS = JS.Eval("(" + СтрокаJSON + ")");
        
        // Извлекаем основные реквизиты чека
        ДатаВремяСтрока = JS.Run("getProp", ЧекJS, "1012"); // Пример: "2020-06-08T21:33:00"
        ФИОКассира = JS.Run("getProp", ЧекJS, "1021");
        ОбщаяСуммаКоп = JS.Run("getProp", ЧекJS, "1020");
        ОбщаяСумма = ОбщаяСуммаКоп / 100;
        
        // Создаем новый документ ЧекККМ в 1С 7.7
        ДокЧек = СоздатьОбъект("Документ.ЧекККМ");
        ДокЧек.Новый();
        ДокЧек.УстановитьВремя(Сред(ДатаВремяСтрока, 12, 2), Сред(ДатаВремяСтрока, 15, 2), Сред(ДатаВремяСтрока, 18, 2));
        ДокЧек.ДатаДок = РабочаяДата(); // или преобразуем дату из строки
        ДокЧек.Комментарий = "Восстановлен автоматически из ОФД. Кассир: " + ФИОКассира;
        
        // Получаем массив позиций чека (тег 1059)
        Позиции = JS.Run("getProp", ЧекJS, "1059");
        РазмерМассива = JS.Run("getArrayLength", Позиции);
        
        Для Инд = 0 По РазмерМассива - 1 Цикл
            СтрокаТовара = JS.Run("getArrayElem", Позиции, Инд);
            
            НазваниеТовара = JS.Run("getProp", СтрокаТовара, "1030");
            Количество = JS.Run("getProp", СтрокаТовара, "1023");
            ЦенаКоп = JS.Run("getProp", СтрокаТовара, "1079");
            СуммаКоп = JS.Run("getProp", СтрокаТовара, "1043");
            
            Цена = ЦенаКоп / 100;
            Сумма = СуммаКоп / 100;
            
            // Ищем номенклатуру в справочнике по наименованию
            СпрНоменклатура = СоздатьОбъект("Справочник.Номенклатура");
            Если СпрНоменклатура.НайтиПоНаименованию(НазваниеТовара, 0, 1) = 1 Тогда
                ТоварСсылка = СпрНоменклатура.ТекущийЭлемент();
            Иначе
                // Если товар не найден, можно использовать предопределенный "Пустой товар" или создавать новый
                ТоварСсылка = ПолучитьПустойТовар();
                Сообщить("Внимание! Товар '" + НазваниеТовара + "' не найден в справочнике номенклатуры.");
            КонецЕсли;
            
            // Заполняем табличную часть документа
            ДокЧек.НоваяСтрока();
            ДокЧек.Номенклатура = ТоварСсылка;
            ДокЧек.Количество = Количество;
            ДокЧек.Цена = Цена;
            ДокЧек.Сумма = Сумма;
        КонецЦикла;
        
        // Записываем и проводим документ
        ДокЧек.Записать();
        ДокЧек.Провести();
        Сообщить("Успешно восстановлен Чек на сумму: " + ОбщаяСумма + " руб.");
        
    Исключение
        Предупреждение("Ошибка парсинга или записи документа: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Профилактика сбоев в работе файловых баз 1С 7.7

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

  1. Перевод базы на SQL: Файловый формат DBF морально устарел и не обеспечивает надежности транзакций при высоких нагрузках и сбоях питания. Оптимальным решением является перевод конфигурации 1С 7.7 на работу под управлением СУБД MS SQL Server.
  2. Проверка ИБП и АКБ: Регулярно (минимум раз в полгода) проводите тестирование аккумуляторных батарей источников бесперебойного питания сервера. При выходе емкости за пределы нормы своевременно меняйте батареи.
  3. Настройка политик кэширования: Если на RAID-контроллере включен режим кэширования записи Write-Back, убедитесь в исправности модуля батарейной защиты кэша (BBU / Flash Backed Write Cache). Если батарея отсутствует или неисправна, переключите контроллер в режим Write-Through (прямая запись на диски без кэширования), несмотря на некоторое падение производительности дисковой подсистемы.
← На главную