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


11

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


興味深い質問なので、いくつか調査を行っていますが、それほど遠くはありません。SQLがそのままでこれをサポートするかどうかはわかりません。
Katherine Villyard 2013

1
これを確認する方法は確かにありますが、LSNを使用することはそれを行う方法ではないかもしれません。私はこの質問には複数のビューを必要とし、数時間で質問に懸賞金を出してあげる...

回答:


12

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


このクエリの結果は正しいようです。
Andreas

確かに私には正しいように見えます。last_log_backup_lsnは、ログの末尾のfirst_lsnと同じです。したがって、Shawnのコードのlast_log_backup_lsnと等しいlast_lsnで復元するログファイルがある場合、最後のログまでのバックアップがあることがわかります。(もちろん、これはクエリの瞬間にのみtrueであることが保証され、次の瞬間に新しいログのバックアップを開始できます。)
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

この記事の 10進数への変換コードの使用。

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


@MartinSmith:fn_dblog十分に文書化されていないようです。その結果は常に現在のデータベースWHERE DbName = 'XXX'に当てはまると思いますか(スニペットにはないため)?
Andreas

@Andreas-はい、文書化されていません。はい、現在のデータベースのログから情報を返します。
マーティン・スミス

元の質問に対する私の編集を参照してください。スニペットによって返される数は、同じDBの最近のバックアップのLSNよりもはるかに大きくなります。
Andreas

@Andreas-奇妙です。私はそれを単一のテストDBで試しただけで、正しく機能しました。エラーの場所がわからない。これを実行しているSQL Serverのバージョンは何ですか?CONVERTスタイルのパラメータは、2問題がある可能性があります。
マーティン・スミス

(とにかく、ショーンの答えはこれよりもはるかに好ましいようですが)
マーティン・スミス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.