Каждый администратор крупных баз данных 1С рано или поздно сталкивается с критическим падением производительности при попытке проанализировать журнал регистрации. Ситуация, когда файл журнала разрастается до 20 ГБ и более, а простая попытка установить отбор по метаданным константы намертво «вешает» сервер 1С и съедает всю доступную оперативную память, весьма распространена.
В этой статье мы подробно разберем, почему платформа 1С:Предприятие (в особенности на версиях 8.3.13) начинает неконтролируемо потреблять ОЗУ при поиске в больших логах, и рассмотрим пошаговые практические методы извлечения нужных данных без вреда для стабильности работающей системы.
Начиная с версии платформы 8.3.12, фирма «1С» внедрила новый формат журнала регистрации, использующий под капотом встроенную СУБД SQLite (файлы с расширением .lgd). Данное нововведение должно было повысить скорость работы с логами, однако на практике привело к ряду серьезных проблем:
rphost.exe или rmngr.exe. Это мгновенно парализует сервер.1Cv8.lgd-journal, что вызывает цепную реакцию перерасхода ОЗУ.Важное примечание: Проблемы с форматом .lgd оказались настолько серьезными, что в более новых версиях платформы (начиная с 8.3.22) фирма «1С» полностью отказалась от формата SQLite, вернув надежный текстовый формат как единственный стандартный вариант.
---
Если нам необходимо всего лишь узнать, какой пользователь и когда изменил значение конкретной константы, самым быстрым и безопасным решением будет чтение файла базы данных SQLite напрямую, в обход зависающих механизмов 1С. Для этого мы применим сторонний менеджер баз данных (например, бесплатную утилиту DB Browser for SQLite или DBeaver).
Проанализируем и выполним этот процесс по шагам:
1Cv8.lgd из каталога 1Cv8Log информационной базы в любую временную папку на локальном компьютере. Никогда не выполняйте запросы напрямую к рабочему логу на сервере!
SELECT code, name FROM MetadataCodes WHERE name LIKE '%ИмяВашейКонстанты%';
Предположим, в результате выполнения запроса мы получили значение code = 45. Теперь мы можем извлечь историю изменений этой константы. Составим и запустим оптимизированный запрос, связывающий таблицы логов и пользователей.
Обратите внимание: 1С хранит временные метки в SQLite в виде десятых долей микросекунд (тиков), прошедших с начала нашей эры. Для преобразования этого числа в понятный формат даты и времени в SQL-запросе используется математическая формула пересчета в Unix Epoch:
SELECT
datetime(el.date/10000 - 62135596800, 'unixepoch', 'localtime') AS [Дата и время],
uc.name AS [Пользователь],
el.dataPresentation AS [Новое значение]
FROM EventLog el
JOIN EventLogMetadata elm ON el.rowID = elm.eventLogID
LEFT JOIN UserCodes uc ON el.userCode = uc.code
WHERE elm.metadataCode = 45
ORDER BY el.date DESC
LIMIT 100;
Этот запрос отработает за считанные секунды даже на 20-гигабайтном файле, поскольку выборка происходит по индексированному полю metadataCode и ограничивается первыми 100 результатами.
---
Если при попытке выполнить SQL-запрос СУБД возвращает ошибку database disk image is malformed, это явный признак того, что файл журнала поврежден. Нам потребуется «вылечить» базу данных, пересобрав ее из текстового дампа с помощью консольной утилиты sqlite3.exe.
Рассмотрим последовательность действий для восстановления:
sqlite3.exe с официального сайта разработчиков SQLite и поместим ее в одну папку с копией нашего битого файла лога.
sqlite3.exe 1Cv8.lgd .dump > dump.sql
dump.sql в любом мощном текстовом редакторе (например, Notepad++). Прокрутим файл в самый конец. Если последней строкой файла идет инструкция ROLLBACK; (что означает аварийное прерывание транзакции), заменим ее вручную на слово COMMIT; и сохраним изменения.
sqlite3.exe 1Cv8_fixed.lgd < dump.sql
sqlite3.exe 1Cv8_fixed.gd "VACUUM;"
После завершения процедур файл 1Cv8_fixed.lgd можно переименовать обратно в 1Cv8.lgd. Теперь он полностью работоспособен, не содержит логических ошибок и готов к быстрому чтению.
---
Если вы хотите решить задачу без использования внешних СУБД, исключительно внутри платформы 1С:Предприятие, никогда не открывайте журнал регистрации интерактивно через Конфигуратор на таких объемах данных. Вместо этого напишем простую внешнюю обработку и запустим ее на сервере.
Использование встроенного метода ВыгрузитьЖурналРегистрации() со строгим ограничением периода поиска и фильтрацией по конкретным метаданным не вызывает перегрузки ОЗУ, так как платформа запрашивает у SQLite строго ограниченный массив записей.
Посмотрим на пример кода внешней обработки:
// Создаем структуру отбора
Отбор = Новый Структура;
// Обязательно указываем жесткое ограничение по метаданным константы
Отбор.Вставить("Метаданные", Метаданные.Константы.ИмяНужнойКонстанты);
// Настоятельно рекомендуем сузить период поиска, например, последними 30 днями
Отбор.Вставить("ДатаНачала", НачалоДня(ТекущаяДата() - 30 * 86400));
// Инициализируем таблицу для выгрузки результатов
ТаблицаРезультат = Новый ТаблицаЗначений;
// Выполняем быструю выборку на сервере
ВыгрузитьЖурналРегистрации(ТаблицаРезультат, Отбор);
// Теперь ТаблицаРезультат содержит только нужные нам записи, ее можно вывести на форму
---
Чтобы раз и навсегда предотвратить повторение подобных проблем на базах крупного объема, мы рекомендуем отказаться от нестабильного формата логов SQLite и вернуться к проверенной временем классике.
Давайте разберем алгоритм безопасного перехода обратно на текстовый формат .lgf:
1Cv8Log вашей информационной базы на сервере и перенесем все файлы с расширением .lgd в отдельную архивную папку вне каталога 1С.1Cv8Log создадим пустой текстовый файл и назовем его 1Cv8.lgf (с пустым содержимым).Для минимизации размеров файлов логов обязательно настроим их разделение по периодам. Для этого в Конфигураторе зайдем в меню Администрирование — Настройка журнала регистрации и выберем периодичность разделения, например, «По неделям» или «По месяцам».
В этом случае вместо одного гигантского файла система будет создавать множество небольших файлов с расширением .lgp. Старые файлы за прошедшие месяцы можно будет легко переносить в архив или удалять обычными средствами операционной системы, а оперативный поиск за текущий период станет мгновенным.