Bar

SQL Server CHECKDBの修復オプション[REPAIR_ALLOW_DATA_LOSS]、恐ろしや・・・

SQL Serverのバックアップから復元するトレーニングを行うため、以前作成した手順を確認してみました。
復元手順書を読み返した時に気が付いた事は、CHECKDBの[REPAIR_ALLOW_DATA_LOSS]レベルを使った復旧作業をした事がない事。
手順の確認は一時ペンディングしてテストを行った結果、Microsoft Technetに記載されている通り「非常にまずい状況」となりましたのでメモ。
今回の内容を教訓に、「CHECKDBの[REPAIR_ALLOW_DATA_LOSS]レベルは今後使わない」事に決め、基本である「バックアップ ファイルから復元」のみとしたいです。

REPAIR オプションは最後の手段

Microsoft Technetの[REPAIR_ALLOW_DATA_LOSS | REPAIR_FAST | REPAIR_REBUILD]項目には、”REPAIR オプションは最後の手段としてだけ使用ください。”と明記されています。特に”REPAIR_ALLOW_DATA_LOSS”レベルは「修復を実行するとデータが失われる事があり、事前にバックアップする事!」と明記されています。
image
正直「最後の手段なんかい?」と思った数分後、テストデータがすべて吹き飛びました
もともと飛ばしていいデータですから、痛くも痒くもありませんが、これが本番データだと思うと恐ろしすぎです。

今回のテスト内容

データベースを論理的に破損させ、復旧オプション付きのCHECKDBを実行してみました。

USE TestDB
GO
ALTER DATABASE TestDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
DBCC CHECKDB('TestDB', REPAIR_ALLOW_DATA_LOSS)
GO
ALTER DATABASE TestDB SET MULTI_USER
Go

結果ログの最後尾に「一貫性エラーが解決されました!」と書かれていますが、修復内容をよ~く読むと、ファイルID:1、ページID:78(1:78)に問題があり、整合性がとれないためオブジェクトから切り離され、データが消失したようなアラートがあります。


'emp' の DBCC 結果。
修復: Clustered インデックスは、データベース "TestDB" のオブジェクト "dbo.emp" で正しく再構築されました。
修復: ページ (1:78) が、オブジェクト ID 2105058535、インデックス ID 1、パーティション ID 72057594038845440、アロケーション ユニット ID 72057594039894016 (型 In-row data) から割り当て解除されました
メッセージ 8945、レベル 16、状態 1、行 2
テーブル エラー: オブジェクト ID 2105058535、インデックス ID 1 は再構築されます。
        エラーは修復されました。
メッセージ 8928、レベル 16、状態 1、行 2
オブジェクト ID 2105058535、インデックス ID 1、パーティション ID 72057594038845440、アロケーション ユニット ID 72057594039894016 (型 In-row data): ページ (1:78) を処理できませんでした。詳細については、他のエラーを参照してください。
        エラーは修復されました。
メッセージ 8939、レベル 16、状態 98、行 2
テーブル エラー: オブジェクト ID 2105058535、インデックス ID 1、パーティション ID 72057594038845440、アロケーション ユニット ID 72057594039894016 (型 In-row data)、ページ (1:78)。テスト (IS_OFF (BUF_IOERR, pBUF->bstat)) が失敗しました。値は 12584969 と -4 です。
        エラーは修復されました。
メッセージ 8980、レベル 16、状態 1、行 2
テーブル エラー: オブジェクト ID 2105058535、インデックス ID 1、パーティション ID 72057594038845440、アロケーション ユニット ID 72057594039894016 (型 In-row data)。インデックス ノード ページ (0:0)、スロット 0 が、子ページ (1:78) と前の子ページ (0:0) を参照していますが、これらの子ページは見つかりませんでした
        エラーは修復されました。
オブジェクト "emp" の 0 ページには 0 行あります。
CHECKDB により、テーブル 'emp' (オブジェクト ID 2105058535) に 0 個のアロケーション エラーと 3 個の一貫性エラーが見つかりました。
CHECKDB により、テーブル 'emp' (オブジェクト ID 2105058535) で 0 個のアロケーション エラーと 3 個の一貫性エラーが解決されました。
CHECKDB により、データベース 'TestDB' に 0 個のアロケーション エラーと 3 個の一貫性エラーが見つかりました。
CHECKDB により、データベース 'TestDB' で 0 個のアロケーション エラーと 3 個の一貫性エラーが解決されました。
DBCC の実行が完了しました。DBCC がエラー メッセージを出力した場合は、システム管理者に相談してください。

復旧後のテーブルを検索するとデータがありませんでした。

この結果より、CHECKDBの[REPAIR_ALLOW_DATA_LOSS]レベルによる復旧は成功しテーブルに接続できるようになりましたが、Microsoft Technetの説明どおり、データは損失・・・という結果になりました。
image_thumb[13]




今回のテスト結果はMicrosoft Technetの記事のとおり、CHECKDBの[REPAIR_ALLOW_DATA_LOSS]レベルは最悪の事態を招くという事を体感した非常に良いテストでした。
Facebookのお友達からも助言がありましたが、やはり「毎日取得しているバックアップファイルから復元作業を行うのが最も安全」ですね。
もし、CHECKDBの[REPAIR_ALLOW_DATA_LOSS]レベルを使ってエラーを解決しよう!とお考えの方は、今回の事例を踏まえお止めになった方が宜しいかと思います。
やはり、バックアップは大切ですね~
いいテストでした!