При администрировании систем на платформе 1С:Предприятие часто возникает задача разворачивания резервных копий (бэкапов) баз данных. Например, когда необходимо восстановить базу на определенный момент времени, проверить актуальность данных в тестовой среде или расследовать инцидент безопасности. В таких случаях перед администратором и разработчиком встает важный вопрос: как определить точную дату и время последнего действия с данными в восстановленной копии?
Ситуация осложняется тем, что при обычном восстановлении базы данных из SQL-бэкапа (файла .bak) стандартный журнал регистрации 1С в новых версиях платформы может оказаться недоступным или устаревшим, поскольку по умолчанию он хранится вне СУБД. В этой статье мы подробно рассмотрим и разберем по шагам все доступные методы решения этой задачи — от простых платформенных механизмов до низкоуровневого анализа СУБД MS SQL Server.
Прежде чем переходить к сложным SQL-запросам, проанализируем стандартные возможности платформы 1С. Если в базе настроено протоколирование действий пользователей, мы можем извлечь эти данные.
Особенности журнала регистрации в новых версиях платформы:
Начиная с версии платформы 8.3.5, журнал регистрации по умолчанию создается в новом формате и представляет собой базу данных SQLite с расширением .lgd. Этот файл хранится на сервере приложений 1С в каталоге кластера, а не внутри базы данных SQL. Соответственно, при создании резервной копии средствами MS SQL Server сам журнал регистрации в бэкап не попадает. Чтобы проанализировать его, нам потребуется перенести файлы ЖР со старого сервера приложений на новый или подключиться к старому серверу и сопоставить события по времени.
Использование версионирования объектов (БСП):
Если в вашей конфигурации (например, 1С:ERP, 1С:КА или 1С:УТ) включен стандартный механизм версионирования объектов БСП (Библиотеки Стандартных Подсистем), задача существенно упрощается. Данные версионирования хранятся непосредственно в таблицах базы данных (в регистре сведений ВерсииОбъектов), а значит, они гарантированно переносятся вместе с SQL-бэкапом.
Для поиска последней версии объекта выполним следующие действия:
ВерсииОбъектов через функции для технического специалиста).Если журнал регистрации не был перенесен, а версионирование отключено, мы можем обратиться напрямую к СУБД. Платформа 1С хранит служебную информацию в системных таблицах, которые восстанавливаются вместе с базой.
Анализ таблицы истории работы пользователей _UsersWorkHistory:
Начиная с платформы 1С 8.2 на управляемых формах, система фиксирует историю активности пользователей. Эти данные записываются в таблицу _UsersWorkHistory. Мы можем написать простой SQL-запрос, чтобы получить максимальную дату активности.
Важный нюанс: 1С хранит даты в SQL-таблицах со смещением (обычно это +2000 лет). Величина смещения хранится в таблице _YearOffset. Нам необходимо учесть это смещение в запросе, чтобы получить реальное время.
Разберем пример SQL-запроса:
DECLARE @Offset INT;
-- Получаем величину смещения дат для данной базы
SELECT TOP 1 @Offset = _YearOffset FROM _YearOffset;
-- Выбираем максимальную дату с учетом смещения
SELECT DATEADD(year, -@Offset, MAX(_Date)) AS LastUserActionTime
FROM _UsersWorkHistory;
Этот запрос вернет точное время последнего интерактивного действия (открытия формы, изменения объекта), зафиксированного платформой.
Анализ таблиц механизма «История данных»:
Если в вашей конфигурации задействован платформенный механизм «История данных» (не путать с версионированием БСП), информация об изменениях записывается в таблицы _DataHistoryVersions (версии данных) и _DataHistoryQueue0 (очередь обновлений истории). Запрос к этим таблицам также позволит быстро определить время последних изменений:
DECLARE @Offset INT;
SELECT TOP 1 @Offset = _YearOffset FROM _YearOffset;
SELECT DATEADD(year, -@Offset, MAX(_Date)) AS LastHistoryChange
FROM _DataHistoryVersions;
Если предыдущие методы не дали результата, мы можем прибегнуть к поиску максимальной даты проведения документов или периодов записей в регистрах. Поскольку документы и движения регистров содержат реальные даты бизнес-операций, анализ этих таблиц покажет, когда была проведена последняя хозяйственная операция.
Для реализации этого метода нам потребуется проанализировать структуру таблиц базы данных. Напишем скрипт, который будет искать максимальные значения дат в таблицах журналов документов (префикс _DocumentJournal), а также в таблицах регистров накопления (_AccumReg) и сведений (_InfoReg).
Рассмотрим пример логики выполнения такого поиска по журналу документов:
DECLARE @Offset INT;
SELECT TOP 1 @Offset = _YearOffset FROM _YearOffset;
-- Пример запроса к конкретному журналу документов (замените имя таблицы на актуальное в вашей базе)
SELECT DATEADD(year, -@Offset, MAX(_Date_Time)) AS LastDocumentDate
FROM _DocumentJournal52;
Чтобы автоматизировать этот процесс, можно написать динамический SQL-запрос, который переберет все системные таблицы, содержащие колонки типа datetime, и выведет максимальное значение среди них. Это даст гарантированный результат, отражающий последнюю проведенную операцию в системе.
Каждое изменение данных в MS SQL Server фиксируется в журнале транзакций (файле с расширением .ldf). Поскольку при восстановлении базы данных восстанавливается и журнал транзакций, мы можем прочитать его системными средствами СУБД.
Для этого мы воспользуемся недокументированной, но крайне полезной системной функцией sys.fn_dblog. Она позволяет проанализировать активную часть журнала транзакций восстановленной базы данных.
Выясним точное время фиксации (коммита) последней транзакции с помощью следующего запроса:
USE [Имя_Вашей_Восстановленной_Базы];
GO
SELECT MAX([End Time]) AS LastTransactionCommitTime
FROM sys.fn_dblog(NULL, NULL)
WHERE Operation = 'LOP_COMMIT_XACT';
Этот метод чрезвычайно точен, так как фиксирует абсолютно любое изменение данных на уровне СУБД, произошедшее непосредственно перед снятием бэкапа.
Важное предостережение: Некоторые специалисты рекомендуют анализировать системное представление sys.dm_db_index_usage_stats и проверять колонку last_user_update. Обратите внимание: этот метод не подходит для восстановленной копии базы! Данная статистика хранится исключительно в оперативной памяти SQL-сервера и сбрасывается при перезапуске службы СУБД, а также при операциях отсоединения, присоединения или восстановления базы данных. В восстановленной базе эта колонка вернет значение NULL.
Если у вас есть доступ к самому файлу резервной копии (.bak), из которого производилось восстановление, мы можем получить важную системную информацию напрямую из него. Время завершения создания резервной копии является гарантированной верхней временной границей: после этого момента данные в восстановленной базе точно не могли изменяться.
Для чтения заголовка бэкапа выполним в среде SQL Server Management Studio (SSMS) команду RESTORE HEADERONLY:
RESTORE HEADERONLY FROM DISK = 'C:\PathToBackup\YourDatabase.bak';
В результирующей таблице проанализируем колонку BackupFinishDate. В ней будет указано точное время, когда процесс создания резервной копии был завершен. Это дает нам четкое понимание того, на какой момент времени актуальны данные в восстановленной базе.
Мы подробно разобрали различные способы определения времени последнего действия с данными. Подведем итоги совместной работы и выберем оптимальный подход в зависимости от условий:
ВерсииОбъектов непосредственно в режиме «1С:Предприятие»._UsersWorkHistory с учетом смещения дат из таблицы _YearOffset.sys.fn_dblog.RESTORE HEADERONLY.