Как восстановить базу данных SQL Server на определенный момент времени для отмены изменений?

Системный администратор IT и автоматизация бизнеса
← На главную

Ситуации, когда массовая обработка данных в 1С привела к ошибкам (например, неправильная замена ссылок на сотрудников, как в данном случае), требуют оперативного вмешательства. Если изменения уже зафиксированы транзакцией, простая отмена действий невозможна. В этом случае нам на помощь приходит механизм восстановления базы данных SQL Server на определенный момент времени (Point-in-Time Recovery).

В этом материале мы подробно разберем, как выполнить эту процедуру, используя SQL Server Management Studio (SSMS) и T-SQL скрипты. Мы также обсудим, как избежать потери данных других пользователей и как проанализировать журнал транзакций.

1. Необходимые условия для восстановления

Прежде чем приступать к действиям, давайте убедимся, что наша среда соответствует требованиям для восстановления на момент времени. Если эти условия не соблюдены, восстановиться можно будет только на момент создания последнего полного бэкапа.

  1. Модель восстановления (Recovery Model): База данных должна находиться в режиме Full (Полная). В режиме Simple журнал транзакций очищается автоматически, и восстановиться на конкретную секунду невозможно.

    Проверить это можно в свойствах базы данных на вкладке Options (Параметры).

  2. Цепочка бэкапов: У вас должен быть полный бэкап (Full Backup), сделанный до момента аварии, и непрерывная цепочка бэкапов журнала транзакций (Transaction Log Backups), покрывающая период от полного бэкапа до момента аварии.

2. Подготовка: Проблема "Хвоста журнала" (Tail-Log Backup)

Частая ошибка, с которой мы сталкиваемся при попытке восстановления — сообщение от SQL Server: "The tail of the log for the database... has not been backed up". Это означает, что в активном журнале транзакций есть данные, которые еще не попали в архив. SQL Server защищает нас от случайной потери этих последних данных.

Перед началом восстановления у нас есть два пути:

  1. Сделать бэкап хвоста журнала: Если вы хотите сохранить данные, введенные после последнего бэкапа (но до момента восстановления), сделайте резервную копию лога с опцией NO_TRUNCATE.
  2. Игнорировать хвост (перезапись): Если цель — откатиться назад и данные после момента "Ч" нам не нужны, мы будем использовать опцию WITH REPLACE (Перезаписать базу).

3. Стратегия безопасности: Восстановление "Рядом" (Side-by-Side)

Давайте рассмотрим самый безопасный сценарий. Вместо того чтобы сразу "убивать" рабочую базу (Production) и накатывать старую версию (что остановит работу всей компании и уничтожит работу других пользователей), мы восстановим копию базы под новым именем (например, Accounting_Restore).

Преимущества такого подхода:

4. Восстановление через SQL Server Management Studio (GUI)

Разберем процесс по шагам, используя графический интерфейс. Интерфейс может незначительно отличаться в разных версиях, но суть остается прежней.

  1. В обозревателе объектов (Object Explorer) нажмите правой кнопкой мыши на папку Databases (Базы данных) и выберите Restore Database (Восстановить базу данных).

    Совет: Если вы восстанавливаете поверх существующей, нажимайте правой кнопкой на саму базу -> Tasks -> Restore -> Database.

  2. В поле To database (В базу данных) введите новое имя (если идем по безопасному пути) или выберите текущее.
  3. В разделе Source for restore (Источник для восстановления) выберите From device и укажите файлы вашего полного бэкапа и всех необходимых бэкапов логов.

    Если история бэкапов сохранилась в msdb, SQL Server может сам заполнить список файлов при выборе базы-источника. Убедитесь, что галочки стоят напротив полного бэкапа и всех последующих логов.

  4. Ключевой момент: Выбор времени.

    Нажмите кнопку Timeline (Временная шкала) или найдите раздел "Point in time" (К моменту времени).

    • Откроется окно, где визуально показана история бэкапов.
    • Выберите пункт Specific date and time (Конкретная дата и время).
    • Установите время до того момента, как была запущена злополучная обработка (например, если обработку запустили в 14:30:00, ставьте 14:29:50).
  5. Перейдите на вкладку Options (Параметры):
    • Если восстанавливаете в новую базу: Убедитесь, что пути к файлам .mdf и .ldf (раздел "Restore the database files as") указывают на новые имена файлов, чтобы не затереть файлы рабочей базы.
    • Если восстанавливаете в текущую базу: Поставьте галочку Overwrite the existing database (WITH REPLACE). Также поставьте галочку Close existing connections to destination database (Закрыть существующие соединения), так как процессы 1С (rphost) могут держать базу и не давать начать восстановление.
  6. Нажмите OK. SQL Server восстановит полный бэкап, а затем последовательно применит журналы транзакций, остановившись ровно в указанную секунду.

5. Восстановление с помощью T-SQL скриптов

Использование скриптов дает больше контроля и понимания процесса. Для восстановления на момент времени критически важно использовать параметр STOPAT.

Предположим, нам нужно восстановиться на состояние 25 апреля 2023 года, 14:30:00.

Шаг 1: Восстановление полного бэкапа в режиме NORECOVERY

Режим NORECOVERY оставляет базу в состоянии "Восстановление" (Restoring...), позволяя накатывать следующие файлы логов. База будет недоступна для пользователей.


-- Если восстанавливаем поверх текущей базы, переводим её в SINGLE_USER, чтобы сбросить соединения 1С
USE master;
ALTER DATABASE Bukhgalteriya SET SINGLE_USER WITH ROLLBACK IMMEDIATE;

RESTORE DATABASE Bukhgalteriya
FROM DISK = 'D:\Backups\Bukhgalteriya_Full.bak'
WITH NORECOVERY, REPLACE;

Шаг 2: Накат промежуточных бэкапов логов (если есть)

Если между полным бэкапом и целевым временем было несколько бэкапов лога, восстанавливаем их по очереди, также в режиме NORECOVERY.


RESTORE LOG Bukhgalteriya
FROM DISK = 'D:\Backups\Bukhgalteriya_Log_1000.trn'
WITH NORECOVERY;

Шаг 3: Накат последнего лога с параметром STOPAT

В последнем файле, который содержит наше целевое время, мы используем параметр STOPAT и переводим базу в рабочее состояние (RECOVERY).


RESTORE LOG Bukhgalteriya
FROM DISK = 'D:\Backups\Bukhgalteriya_Log_1500.trn'
WITH RECOVERY, 
STOPAT = '2023-04-25 14:30:00';

После выполнения этой команды база данных станет доступна и будет содержать данные ровно на 14:30:00. Все транзакции, совершенные после этого времени (даже если они есть в файле бэкапа), будут отброшены.

6. Как узнать, когда именно была ошибка? (Анализ журнала)

В вопросе автора прозвучала важная мысль: "Как посмотреть в журнале какие были исправления?". Стандартный журнал регистрации 1С может показать, кто и когда запускал обработку, но не всегда показывает детали изменений SQL.

Если нам нужно точное время транзакции на уровне SQL, мы можем воспользоваться системной (недокументированной, но популярной) функцией fn_dblog. Она читает активный журнал транзакций.

Посмотрим на пример запроса, который поможет найти массовые изменения:


USE Bukhgalteriya;
SELECT 
    [Current LSN],
    [Transaction ID],
    [Operation],
    [Context],
    [AllocUnitName],
    [Begin Time],
    [Transaction Name]
FROM 
    fn_dblog(NULL, NULL)
WHERE 
    [Begin Time] > '2023-04-25 14:00:00' -- Время начала поиска
    AND [Operation] = 'LOP_BEGIN_XACT' -- Ищем начала транзакций
ORDER BY 
    [Begin Time] DESC;

В результатах мы ищем транзакции, которые начались в предполагаемое время ошибки. Если обработка меняла тысячи записей, мы увидим огромную активность, связанную с операциями LOP_MODIFY_ROW. Найдя точное время [Begin Time] ошибочной транзакции, мы можем выбрать время для восстановления на 1 секунду раньше.

7. Рекомендации для администратора 1С

Подводя итог, выделим главные шаги для безопасного решения проблемы:

  1. Не торопитесь откатывать "боевую" базу. Если прошло много времени, откат уничтожит работу всех бухгалтеров за этот период.
  2. Используйте метод восстановления в новую базу. Восстановите копию на момент "до ошибки".
  3. Сравните данные. Используйте консоль отчетов или простые запросы в 1С, чтобы сравнить справочник сотрудников в текущей (испорченной) базе и в восстановленной копии.
  4. Перенесите корректные данные. Напишите простую обработку или используйте "Выгрузку/Загрузку данных XML", чтобы перенести правильные ссылки из копии в рабочую базу.
  5. Блокировки. Помните, что для восстановления базы SQL Server требуется монопольный доступ. Остановите службу агента сервера 1С или принудительно завершите сеансы через консоль администрирования кластера 1С, иначе получите ошибку "Database is in use".
← На главную