При активной работе с базой данных 1С системные администраторы и разработчики могут столкнуться с критической ошибкой при попытке открыть журнал регистрации: «sqlite3_step failed: database disk image is malformed». Данная ошибка свидетельствует о нарушении целостности файла журнала регистрации нового формата (1Cv8.lgd), который представляет собой базу данных SQLite.
Часто после стандартной процедуры восстановления базы через утилиту командной строки SQLite администраторы замечают, что в журнале осталась лишь часть записей (например, за последние несколько месяцев вместо нескольких лет), при этом сам файл на диске продолжает занимать десятки гигабайт. Разберем подробно, почему это происходит, как извлечь максимум уцелевших данных, как освободить место на диске и правильно организовать хранение истории действий пользователей.
Проанализируем основные факторы, приводящие к нарушению структуры B-Tree в базе данных SQLite журнала регистрации:
rphost или rmngr, внезапное отключение электропитания или жесткая перезагрузка сервера в момент активной транзакции записи в журнал.1Cv8Log антивирусным монитором или блокировка файла службами теневого копирования (VSS) без предварительного сброса дискового кэша.Рассмотрим механизм работы стандартной команды .dump. При выполнении дампа утилита обходит дерево данных от начала к концу. Как только алгоритм натыкается на первый физически поврежденный блок или поврежденный индекс, процесс чтения прерывается, а в конец выгруженного скрипта помещается инструкция ROLLBACK. В результате в результирующий файл попадает только тот фрагмент записей, который находился до точки сбоя (или в неповрежденных ветках), а вся остальная многолетняя история отсекается.
Сохранение большого размера файла объясняется особенностями движка SQLite: при удалении записей или переносе неполного набора данных физическое пространство на диске не возвращается операционной системе автоматически. SQLite помечает освободившиеся страницы как пустые для будущих записей, сохраняя исходный объем файла на диске.
Если стандартный дамп не вернул историю, применим низкоуровневый режим восстановления .recover, доступный в актуальных версиях утилиты SQLite. В отличие от .dump, этот режим выполняет постраничное сканирование файла в обход поврежденных индексов и собирает все уцелевшие строки таблицы.
1C:Enterprise 8.3 Server Agent.1Cv8Log с файлами 1Cv8.lgd, 1Cv8.lgd-wal и 1Cv8.lgd-shm в безопасное место.sqlite3.exe и выполним команду низкоуровневого восстановления:
sqlite3 1Cv8_corrupted.lgd ".recover" > recovered_data.sql
sqlite3 1Cv8.lgd < recovered_data.sql
Если журнал был очищен, сокращен штатными средствами или восстановлен с меньшим количеством записей, но файл по-прежнему занимает много места, выполним принудительную дефрагментацию и упаковку страниц базы данных:
1C:Enterprise Server Agent.1Cv8.lgd и выполним команду сжатия:
sqlite3 1Cv8.lgd "VACUUM;"
Хранить монолитный файл SQLite объемом в десятки гигабайт за 5–8 лет в рабочей базе крайне рискованно. При возникновении сбоя блокируется доступ ко всей истории сразу, а сам журнал начинает создавать повышенную нагрузку на дисковую подсистему. Рассмотрим правильные подходы к организации архивного хранения логов:
Администрирование -> Настройка журнала регистрации можно переключить формат журнала на текстовый с разделением по периодам (например, по месяцам или по годам). В этом случае каждый период сохраняется в отдельный файл. Повреждение текущего дня или месяца никак не повлияет на архивные файлы прошлых лет, а резервное копирование сводится к простому переносу файлов в архивное хранилище.