Резервные копии журнала транзакций SQL Server: проверьте, следует ли хвостовой журнал последней известной резервной копии журнала

11

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

Я уже знаю, как это сделать для существующих резервных копий: используя RESTORE HEADERONLY, я получаю FirstLSN и LastLSN каждого файла, которые можно сравнить для последовательных файлов, чтобы определить, совместимы ли они.

Однако я не знаю, как проверить, следует ли хвостовой журнал последней резервной копии журнала.

Если бы у меня был FirstLSN хвостового журнала, я мог бы сравнить его с LastLSN последней резервной копии журнала. Но как я могу получить FirstLSN хвостового журнала?

Мне нужно решение, которое работает с SQL Server 2005 и выше (в идеале, используя t-sql). До сих пор я искал Google безрезультатно. Btw. Я впервые опубликовал это на stackoverflow; но перенесли это сюда, так как это было отмечено не по теме.

РЕДАКТИРОВАТЬ

Я попробовал два предоставленных решения на небольшом примере (SQL Server 2005, 9.0.5057):

BACKUP DATABASE TestDb TO DISK = 'C:\temp\backup test\Full.bak' 

-- fire some update queries

BACKUP LOG TestDb TO DISK =  'C:\temp\backup test\Log1.bak' 

-- fire both queries from the provided answers: 
-- Martin Smith's answer yields: 838886656088920652852608
-- Shawn Melton's answer yields: 46000000267600001

RESTORE HEADERONLY FROM DISK = 'C:\temp\backup test\Log1.bak'  
-- yields: 46000000267600001

Таким образом, кажется, что первый выключен на несколько порядков.

Затем я провел такой же тест на SQL 2008 SP1 (10.00.2531), где оба запроса дали правильный ответ.

Andreas
источник
Я проводил некоторые исследования, потому что это интересный вопрос, но я не захожу слишком далеко. Я не уверен, что SQL поддерживает это из коробки.
Кэтрин Вилльярд
1
Я уверен, что есть способ проверить это, возможно, использование LSN не способ сделать это. Я назначу награду за этот вопрос через несколько часов, этот вопрос нуждается в большем количестве просмотров ...

Ответы:

12

Я обратился к своей копии внутренних компонентов SQL Server 2008, и было указано на DMV sys.database_recovery_status , чтобы найти первый номер LSN следующей резервной копии журнала. Какой столбец BOL last_log_backup_lsnпредоставляет вам:

Порядковый номер журнала самой последней резервной копии журнала. Это конечный LSN предыдущего резервного копирования журнала и начальный LSN следующего резервного копирования журнала.
NULL = Нет резервной копии журнала. База данных находится в автономном режиме или база данных не запустится.

Также стоит упомянуть, что Kalen также поднимает вопрос о том, что вы получите значение NULL, если база данных находится в режиме ПРОСТОГО восстановления (режим автообрезки) или если не существует резервной копии журнала.

Но как я могу получить FirstLSN хвостового журнала?

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

Поэтому выполнение следующего вернет значение, которое, я полагаю, вы ищете:


SELECT 
   last_log_backup_lsn
FROM 
   sys.database_recovery_status
WHERE 
   databse_id = DB_ID('MyDb')

Этот DMV доступен начиная с SQL 2005.

РЕДАКТИРОВАТЬ
Если вы не прочитали ссылку BOL, обратите внимание, что этот DMV будет возвращать значения только в те базы данных, которые находятся в сети или открыты, так как BOL ссылается на нее. Если происходит сбой, требующий от вас резервного копирования хвостового журнала базы данных, вы не сможете проверить это значение с помощью приведенного выше кода, если база данных не доступна; что в случае неудачи, вероятно, не будет.


источник
Результат этого запроса представляется правильным.
Андреас
Конечно, выглядит правильно для меня. Last_log_backup_lsn равно first_lsn хвоста журнала. Итак, если у вас есть файл журнала, который нужно восстановить с last_lsn, равным last_log_backup_lsn из кода Шона, то вы знаете, что у вас есть резервная копия вплоть до хвостового журнала. (Конечно, это гарантировано только в момент запроса, в следующий момент может быть запущена новая резервная копия журнала.)
RLF
@RLF добавил дополнительное примечание, потому что это также будет верно, если база данных недоступна. Это не совсем жизнеспособное решение для использования при реализации плана аварийного восстановления. Чисто для настольных упражнений или проверки вашего плана.
6

Что-то вроде следующего должно сделать это.

WITH LSN_CTE
AS
(
SELECT TOP 1
       LEFT( LogRecords.[Current LSN], 8 )          AS Part1,
       SUBSTRING( LogRecords.[Current LSN], 10, 8 ) AS Part2,
       RIGHT( LogRecords.[Current LSN], 4 )         AS Part3
FROM   sys.fn_dblog(NULL,NULL) AS LogRecords
ORDER BY [Current LSN]
)
SELECT CAST( CAST( CONVERT( varbinary, Part1, 2 ) AS int ) AS varchar ) +
       RIGHT( '0000000000' + CAST( CAST( CONVERT( varbinary, Part2, 2 ) AS int ) AS varchar ), 10 ) +
       RIGHT( '00000'      + CAST( CAST( CONVERT( varbinary, Part3, 2 ) AS int ) AS varchar ), 5 ) AS [Converted LSN]
FROM   LSN_CTE

Использование кода преобразования в десятичную из этой статьи .

ORDER BY [Current LSN]Вполне может быть совершенно ненужным над головой. Я не уверен. Результат этой функции всегда выглядит в порядке LSN, и я думаю, он просто читает журнал последовательно, но на всякий случай ...

Мартин Смит
источник
@MartinSmith: fn_dblogпохоже, не очень хорошо задокументировано. Я предполагаю, что его результаты всегда верны для текущей базы данных (так как WHERE DbName = 'XXX'в фрагменте их нет)?
Андреас
@ Андреас - Да, это без документов. И да, он возвращает информацию из журнала текущей базы данных.
Мартин Смит
см. мое редактирование к исходному вопросу. Число, возвращаемое вашим фрагментом, намного больше, чем номера LSN недавних резервных копий одной и той же БД.
Андреас
@ Андреас - Странно. Я только попробовал это на единственной тестовой БД, и это работало правильно. Не уверен, где ошибка. На какой версии SQL Server вы это используете? Параметр CONVERTwith style 2может быть проблемой.
Мартин Смит
(Хотя в любом случае ответ Шона кажется гораздо более предпочтительным, чем этот)
Мартин Смит