web-dev-qa-db-ja.com

SQL Serverトランザクションログバックアップ:最後の既知のログバックアップの後にテールログが続くかどうかをテストする

SQL Serverを完全復旧モードで使用しています。完全バックアップと一連のログバックアップを前提として、最後の完全バックアップから現在の末尾ログまでのログチェーンが完了しているかどうかを確認できるようにしたいと考えています。 (これらのバックアップを実際に復元することなく、ここでの目的はバックアップの一貫性をテストすることです。)

既存のバックアップでこれを行う方法はすでに知っています。RESTOREHEADERONLYを使用して、すべてのファイルのFirstLSNとLastLSNを取得します。これらのファイルは、互換性があるかどうかを判断するために、連続ファイルで比較できます。

ただし、最後のログバックアップの後にテールログが続くかどうかを確認する方法がわかりません。

テールログのFirstLSNがある場合、それを最後のログバックアップのLastLSNと比較できます。しかし、どうすれば末尾ログのFirstLSNを取得できますか?

SQL Server 2005以降(理想的にはt-sqlを使用)で機能するソリューションが必要です。これまでのところ、私は無駄にグーグルを検索してきました。ところで私は最初にこれをstackoverflowに投稿しました。トピックから外れているため、ここに移行しました。

[〜#〜]編集[〜#〜]

小さな例(SQL Server 2005、9.0.5057)で提供された2つのソリューションを試しました。

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)で同じテストを行いました。どちらのクエリでも正しい答えが得られました。

11
Andreas

SQL Server 2008 Internals のコピーに目を向けると、次のログバックアップの最初のLSNを見つけるために、DMV sys.database_recovery_status が指摘されました。どちらの列をBOLするかlast_log_backup_lsnは以下を提供します。

最新のログバックアップのログシーケンス番号。これは、前のログバックアップの終了LSNと次のログバックアップの開始LSNです。
NULL =ログバックアップは存在しません。データベースがオフラインであるか、データベースが起動しません。

また、Kalenは、データベースがSIMPLEリカバリモード(自動切り捨てモード)である場合、またはログバックアップが存在しない場合に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が参照するデータベースとして開かれているデータベースにのみ値を返すことに注意してください。データベースのログ末尾のバックアップを取る必要がある障害が発生した場合、データベースにアクセスできない限り、上記のコードではこの値を確認できません。失敗した場合、それはおそらくありません。

12
user507

次のようなものがそれを行うはずです。

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

この記事 から10進数への変換コードを使用します。

ORDER BY [Current LSN]は、完全に不必要なオーバーヘッドになる可能性があります。よく分かりません。この関数の結果は常にLSN順になっているようで、念のためにログを順番に読み取るだけだと思います...

6
Martin Smith