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

  1. Исходная база данных (назовем ее основной копией) находится в режиме ведения журнала. Нельзя выполнить пересылку журналов без создания резервных копий журналов транзакций после всех транзакций.
  2. Вам нужно «завести» резервную копию, чтобы создать целевую копию базы данных. Эта целевая копия должна быть в состоянии восстановления, то есть она может принимать дополнительные резервные копии, которые применяются в порядке, обеспечивающем непрерывность транзакций (см. статью «Базовые принципы резервирования для администратора: восстановление», опубликованную в этом же номере журнала).
  3. Четыре задания агента SQL Server, которые могут быть созданы автоматически с помощью мастера или вручную с использованием T-SQL: запись резервных копий в журнал транзакций на хост-компьютере для основной копии базы данных; копирование резервных копий в сетевое расположение по вашему выбору; и наконец, задание восстановления для применения журналов транзакций к целевой копии базы данных. Дополнительное задание — отслеживать успех или неудачу каждого шага процесса.

Несколько причин могут привести к сбою в процессе пересылки журналов. Некоторые из отказов, в частности резервные копии, которые не были сформированы из основной базы данных, например из-за недостатка места на диске, опаснее других. В любом случае, когда пересылка журналов прекращается и вы получаете предупреждение от агента SQL Server (если вы подготовили схему уведомлений для задания предупреждения), вы должны иметь иметь возможность быстро восстановить пересылку журналов. Обычно в ситуации с пересылкой журналов пользователи делают резервные копии журналов транзакций (через каждые пять минут и даже чаще, в зависимости от интенсивности транзакций). Таким образом, даже в случае, когда пользователь подключен к сети в рабочие часы, ему, возможно, придется устранять отказ в то самое время, когда резервные копии продолжают поступать. При этом невозможно определить, какую резервную копию журналов транзакций следует применить, если простой перезапуск задания восстановления агента SQL Server не помогает.

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

Путеводная нить — номер LSN

Номер Log Sequence Number (LSN), или регистрационный номер транзакции в журнале, представляет собой путеводную нить, с помощью которой процесс восстановления в SQL Server определяет порядок применения транзакций. Все процессы восстановления должны выполняться в определенном порядке, чтобы прочитать транзакции из журнала транзакций и файлов резервных копий журналов в том же порядке, в котором они изначально применялись к основной базе данных.

Обычно мы начинаем читать книгу с первой страницы (кроме пессимистов, не уверенных, что им суждено дочитать до конца, эти начинают с последней страницы, я знаю таких). Журнал транзакций читают таким же образом. Иногда пересылка журналов зависает и уже неизвестно, в каком месте книги произошла остановка, — закладка потеряна. Причиной может быть прекращение резервного копирования, как отмечалось выше, или сбой процесса копирования, после которого процесс восстановления не может найти следующий журнал, чтобы выстроить цепь событий резервного копирования. После того как проблема устранена, остается лишь запустить задание восстановления в мониторе активности заданий агента SQL Server, но и здесь возможна неудача. В этом случае нужно найти следующую резервную копию журнала транзакций в цепи событий и запустить процесс, применив именно эту резервную копию журнала или полную резервную копию, а затем начать выполнять задание восстановления пересылки журналов. Ключ ко всему — поиск резервной копии со следующим номером LSN в цепи резервного копирования.

Перезапуск процесса пересылки журналов вручную

Если выясняется, что необходимо быстро применить следующую резервную копию файла журнала в последовательности, чтобы возобновить процесс пересылки журналов, то достаточно идентифицировать следующую резервную копию в цепочке и убедиться, что она находится в предполагаемом каталоге восстановления. С помощью таблицы msdb.dbo.log_shipping_monitor_secondary можно идентифицировать последнюю созданную резервную копию журнала транзакций, последнюю восстановленную резервную копию журнала транзакций, а затем убедиться, что следующая резервная копия журнала транзакций, сделанная на основном экземпляре, скопирована в целевой каталог восстановления наряду с любыми другими, если задание копирования было остановлено. После того как это сделано, вы сможете вручную перезапустить задание агента SQL Server для корректного восстановления пересылки журналов (см. листинг 1 и результаты на экране 1).

 

Результаты перезапуска задания агента SQL Server вручную
Экран 1. Результаты перезапуска задания агента SQL Server вручную

 

Затем можно переключиться на экземпляр SQL Server основной базы данных и журнал резервного копирования журнала транзакций для базы данных, чтобы определить журнал транзакций, следующий за последним восстановленным файлом (см. листинг 2).

Это дает результаты (на экране 2 показан фрагмент) с упорядочением по backup_finish_date до самой недавней резервной копии для основной копии базы данных.

 

Порядок журналов транзакций до самого последнего
Экран 2. Порядок журналов транзакций до самого последнего

 

Взглянув на первую запись в крайнем правом столбце на экране 2, вы получите представление динамических выходных данных SQL для восстановления (см. листинг 3).

Так что же именно было сделано в этом процессе?

  1. На целевом экземпляре копии базы данных мы направили запрос к msdb.dbo.log_shipping_monitor_secondary, чтобы идентифицировать последний восстановленный файл резервной копии.
  2. С помощью полученной информации мы перешли к экземпляру основной базы данных, чтобы получить историю резервного копирования журнала транзакций, содержащего сведения обо всех действиях на исходной базе данных после последнего применения резервной копии. Сценарий создает динамическую команду восстановления, которую затем можно выполнить на целевом экземпляре для повторного запуска процесса пересылки журналов.
  3. На данном этапе у нас должна появиться возможность перезапустить задание восстановления пересылки журналов агента SQL Server.

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

  • msdb.dbo.backupset, предоставляет время начала и окончания резервного копирования для каждого файла резервной копии в метаданных, сохраненных в msdb. Это представление системного каталога также дает нам имя сервера, имя базы данных и столбец media_set_id, необходимые для последующего объединения с msdb.dbo.backupmediafamily.
  • msdb.dbo.backupmediafamily, содержит важный элемент мозаики — физический файл для резервных копий журнала транзакций на основной базе данных.
  • msdb.dbo.log_shipping_primary_databases; это представление каталога дает сведения о пересылке журналов для передачи резервной копии (куда «отправляются» журналы транзакций для восстановления на вторичном, или целевом, экземпляре).

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

Листинг 1. Ручной перезапуск задания агента SQL Server 
SELECT last_copied_file
        , last_restored_file
        , last_copied_date
        , last_restored_date
        , last_restored_latency
FROM msdb.dbo.log_shipping_monitor_secondary
WHERE secondary_database = 'sm_FOO';
Листинг 2. Определение следующего журнала транзакций
WITH full_backups AS
(
SELECT
        ROW_NUMBER() OVER(PARTITION BY database_name ORDER BY database_name
        ASC, backup_finish_date DESC) AS [Row Number],
        server_name,
        database_name,
        backup_set_id,
        backup_finish_date,
        last_lsn,
        media_set_id
FROM msdb.dbo.[backupset]
WHERE [type] = 'L'
        AND [database_name] = 'sm_Panel'
)

SELECT TOP 10
        FB.server_name,
        FB.database_name,
        FB.backup_finish_date,
        BMF.physical_device_name AS primary_database_physical_device_name,
        'RESTORE LOG [' + FB.database_name + '] FROM  DISK = N''' + PD.backup_share +
        RIGHT(BMF.physical_device_name, LEN(BMF.physical_device_name) - LEN
        (PD.backup_directory))  + ''' WITH  FILE = 1,  NORECOVERY,  NOUNLOAD,  STATS =
        10' AS restore_command_for_log_shipped_copy
FROM full_backups FB
INNER JOIN msdb.dbo.backupmediafamily BMF ON FB.media_set_id = BMF.media_set_id
INNER JOIN msdb.dbo.log_shipping_primary_databases PD ON FB.database_name =
PD.primary_database
WHERE FB.backup_finish_date > '2016-09-07 13:00:00.000'
ORDER BY FB.[Row Number] DESC;
Листинг 3. Получение динамических данных SQL для восстановления
RESTORE LOG [sm_FOO]
FROM  DISK = N'\\SQL-DR-123\Backup\TxLogs\sm_FOO\sm_FOO_20160907200000.trn'
WITH  FILE = 1,  NORECOVERY,  NOUNLOAD,  STATS = 10