SQL Server のデータベースのリストア検証をするためにデータベースを破損させる必要のあることがあります。
データベースを意図的に破損させる方法について軽く書いてみたいと思います。
データベースのリストアを検証する場合、以下の 2 パターンを試す時があるかと思います。
- データベースの破損
- データページの破損
データベースの破損はデータベースのヘッダ領域や一部のファイルが破損してしまいデータベースにアクセスができない状態となります。このケースではログ末尾のバックアップの取得を行い、障害発生の直前までリストアをする検証をするパターンが考えられます。
データページの破損はページ単位のリストアやデータベースミラーリング / AlwaysOn 可用性グループのページの自動修復 / DBCC CHECKDB REPAIR_ALLOW_DATA_LOSS を使用した修復の検証をするパターンが考えられるかと。
それぞれのパターンでデータベースを実際に破損させてみたいと思います。
Contents
■データベースの破損
データベースを破損させるための方法としては、
- バイナリエディタでデータファイルの先頭を 0 で初期化する
# 先頭の適当なデータが入っている個所をクリアすればデータベースのファイル破損となり、データベースをアクティブにできなくなるかと。 - SQL Server のサービスを停止し、mdf or ndf ファイルを削除する
というような方法があるかと。
これにより、データベースにアクセスができない状態からの検証をすることが可能です。
トランザクションログのファイルが生きていれば、データベースにアクセスできなくても、
BACKUP LOG RESTORETEST TO DISK='RESTORETEST.trn' WITH NORECOVERY,CONTINUE_AFTER_ERROR
というような SQL でログ末尾のバックアップを取得することが可能です。
それまでに取得していたバックアップ + ログ末尾のバックアップがあればデータファイルが完全に削除されている状態でもデータベースのリストアをすることができます。
■データページの破損
特定のページを破損させるための方法としては、
- バイナリエディタで非 Unicode 文字列を検索し、該当の箇所を書き換える
- DBCC WRITEPAGE を使用してページを書き換える
といった方法があるかと。
データ圧縮をすると Compression Data Array (CDA) の形式になってしまうためデータの判別ができないのですが、データ圧縮をしていない場合は、バイナリエディタで非 Unicode 文字列を簡単に検索することができます。
また、以前 DBCC WRITEPAGE を使用したダイレクトなページの書き換え で書いたのですが、DBCC WRITEPAGE を使用することでページの情報を書き換えることが可能です。
以下のようなクエリでデータが格納されているページ番号を取得することができます。
SELECT * FROM Table_1 CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%)
取得したページ番号を使用して、DBCC WRITEPAGE でページの情報を直接書き換えます。
ALTER DATABASE RESTORETEST SET SINGLE_USER DBCC WRITEPAGE ('RESTORETEST', 1, 90, 11, 8, 0x0000000000000000, 1) ALTER DATABASE RESTORETEST SET MULTI_USER
SQL Server では通常データページの整合性をページの内容を元に算出したチェックサムにより確認をしています。
そのため、チェックサムを変更せずにページを書き換えた場合、整合性が保ていない状態となるためページ破損として検出がされます。
この状態を作り出すことでページ単位のリストアを検証することが可能となります。
実運用では使用することはないかと思いますが、リストアの検証をする際にはこれらの方法で破損状態を作り出すことにより、リストアのパターンが広がるかと。