Как восстановить удаленные данные из очищенного журнала регистрации 1С?

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

Журнал регистрации 1С является критически важным инструментом для расследования инцидентов, анализа действий пользователей и поиска виновников некорректного изменения данных. Начиная с версии платформы 1С:Предприятие 8.3, формат журнала регистрации по умолчанию изменился со старого текстового (файлы .elf) на новый последовательный формат баз данных SQLite (файл с расширением .lgd).

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

Физическая структура SQLite и поведение при удалении данных

Для понимания процесса восстановления важно проанализировать, как СУБД SQLite (на которой базируется файл .lgd) обрабатывает операции удаления строк. Когда мы сокращаем журнал регистрации штатными средствами 1С, платформа выполняет SQL-запрос на удаление записей из таблицы EventLog по определенному временному условию. При этом физический размер файла журнала на диске остается прежним.

Выясним причину этого явления. SQLite оптимизирует дисковые операции записи и чтения. Вместо постоянного изменения размера файла операционной системы при каждом удалении строк, СУБД использует механизм свободных страниц (Freelist) и нераспределенного пространства внутри страниц (Unallocated Space):

  1. Списки свободных страниц (Freelist): Когда удаляется целый пласт данных (например, миллионы строк за прошлый год), освободившиеся страницы данных базы помечаются как неиспользуемые и заносятся в специальный список. С точки зрения операционной системы файл базы данных не уменьшается. СУБД держит эти страницы «про запас» для будущих записей.
  2. Свободное место внутри страниц (Unallocated Space): Если удаляется только часть строк на странице, сама страница остается активной, но внутри нее образуются «пустоты» — свободные байты, готовые принять новые записи.

Физически удаленные записи остаются внутри файла .lgd до тех пор, пока на их место не будут записаны новые события журнала регистрации. Если после сокращения журнала база данных не сжималась принудительно (команда VACUUM), старые данные все еще находятся на диске. Однако, если после очистки велась активная работа пользователей в 1С, новые логи постепенно перезаписывают страницы из списка Freelist, безвозвратно уничтожая старую информацию.

Метод 1. Восстановление данных с помощью скрипта sqlite2csv

Рассмотрим практический способ восстановления структуры удаленных таблиц с помощью специализированного Python-скрипта sqlite2csv (SQLite 2 CSV conversion and recovery tool). Этот инструмент сканирует файл базы данных низкоуровневым методом, извлекая как живые, так и помеченные как удаленные строки, после чего сохраняет их в текстовом формате CSV.

Разберем по шагам процесс использования данного скрипта:

  1. Убедимся, что на компьютере установлен интерпретатор Python актуальной версии. При необходимости скачаем его с официального сайта.
  2. Скачаем скрипт sqlite2csv.py из репозитория разработчиков.
  3. Скопируем наш файл журнала регистрации 1Cv8.lgd в отдельный рабочий каталог (категорически запрещается проводить любые манипуляции непосредственно с активным файлом журнала на работающем сервере 1С!).
  4. Запустим командную строку или терминал и перейдем в папку со скриптом. Выполним команду для сканирования и экспорта данных:

python sqlite2csv.py -i 1Cv8.lgd -o output_directory --recovery

Параметр -i указывает на исходный файл базы данных, параметр -o задает целевой каталог для сохранения CSV-файлов, а ключ --recovery активирует режим поиска удаленных и поврежденных записей в обход заголовков страниц СУБД. В результате успешного выполнения утилита создаст набор CSV-файлов, соответствующих таблицам журнала регистрации (основной интерес представляет таблица EventLog).

Почему восстановленные поля могут содержать NULL-значения?

Иногда при использовании автоматических скриптов администраторы сталкиваются со следующей проблемой: строки восстанавливаются, но практически все значимые поля (имя пользователя, представление данных, комментарий) заполнены значениями NULL. Проанализируем, почему так происходит:

Метод 2. Извлечение данных утилитой низкоуровневого восстановления Undark

Если скрипт на Python не дал желаемого результата, воспользуемся более мощным консольным инструментом с открытым исходным кодом — Undark. Эта утилита разработана специально для криминалистического анализа поврежденных и очищенных баз данных SQLite. Она полностью игнорирует внутренние индексы СУБД, сканируя файл байт за байтом в поисках сигнатурных совпадений валидных записей.

Для восстановления данных выполним следующую последовательность действий:

  1. Скачаем скомпилированную версию утилиты Undark для вашей операционной системы.
  2. Поместим утилиту и исследуемый файл 1Cv8.lgd в один каталог.
  3. Запустим утилиту через командную строку, перенаправив вывод в текстовый файл SQL-дампа:

undark -i 1Cv8.lgd -d recovered_dump.sql

Утилита попытается воссоздать структуру удаленных таблиц в виде стандартных SQL-инструкций INSERT INTO. Полученный дамп-файл можно открыть в любом продвинутом текстовом редакторе или импортировать в новую пустую базу данных SQLite для последующего анализа.

Метод 3. Сигнатурный поиск в HEX-редакторе

В случаях, когда автоматизированные утилиты восстановления пасуют перед фрагментированной структурой файла, последней надеждой остается ручной низкоуровневый анализ содержимого файла в HEX-редакторе (например, HxD, WinHex или встроенные средства просмотра крупных файлов). Этот метод позволяет однозначно ответить на вопрос: физически ли стерты искомые данные из файла, или они все еще там присутствуют.

Выполним поиск по уникальным текстовым константам:

Если HEX-редактор находит текстовые совпадения в теле файла .lgd среди неразмеченных областей данных, значит, информация физически уцелела. Извлечь ее в таком случае можно путем написания регулярных выражений или скрипта разбора бинарного потока под конкретную сигнатуру записи.

Важное дополнение: файлы WAL и SHM

При анализе логов SQLite обязательно нужно обращать внимание на сопутствующие временные файлы, которые создаются в той же директории, где лежит основной файл базы данных:

Если сокращение журнала регистрации или последующее аварийное завершение работы сервера произошло некорректно, значительная часть удаленных (или, наоборот, новых) транзакций могла «застрять» в файле -wal. При переносе файла журнала для восстановления на другой ПК обязательно копируйте всю тройку файлов вместе. Если открыть .lgd без соответствующего ему оригинального .lgd-wal, СУБД может автоматически откатить незавершенные транзакции, что приведет к окончательной потере ценных данных.

Рекомендации по безопасному администрированию журнала регистрации

Чтобы в будущем не сталкиваться с необходимостью восстановления поврежденной и удаленной информации из SQLite, выработаем правильный регламент обслуживания журналов регистрации 1С:

  1. Регулярное резервное копирование: Файл 1Cv8.lgd не бэкапится стандартными средствами резервного копирования СУБД (MS SQL, PostgreSQL), так как лежит в каталоге кластера 1С. Настройте скрипты архивации (например, теневое копирование VSS или архиваторы через планировщик задач ОС) для регулярного копирования каталога журнала при остановленной службе сервера 1С или с использованием специализированных утилит копирования заблокированных файлов.
  2. Разделение файлов по периодам: Начиная с версии 1С 8.3.21+, платформа позволяет настраивать автоматическое разделение журнала регистрации на отдельные файлы по периодам (например, помесячно или по годам). Это полностью решает проблему ручной «обрезки» — старый архивный файл за прошлый год можно просто перенести в долгосрочное хранилище, не затрагивая текущий рабочий лог.
← На главную