今回は [データベースのリストア] について振り返っていきたいと思います。
バックアップポリシーの中で、以下のような図を使用してバックアップについての説明がありました。
セミナーの中で、障害発生のタイミングでデータベースの障害が発生した場合どのタイミングまでリストアすることが可能なのかという質問がありました。
この質問の内容を元にリストアについてまとめていきたいと思います。
■環境の準備
[RESTORE_TEST] というデータベースに [TEST] というテーブルを作成しています。
# 復旧モデルは [完全復旧モデル] としています。
このテーブルに以下のようなクエリを実行してデータを挿入します。
SET NOCOUNT ON |
この状態を [完全バックアップ] で取得します。
取得したバックアップを最初の状態の [月 22:00] に取得したものとします。
続いて、以下のクエリを実行します。
SET NOCOUNT ON |
それでは、この状態のバックアップを [トランザクションログ バックアップ] で取得します。
このバックアップを [火 12:00] に取得したものとします。
もう一つ、ログのバックアップを取得するために以下のクエリを実行してデータを挿入します。
SET NOCOUNT ON |
それでは、この状態をトランザクションログのバックアップとして取得します。
このバックアップが [火 18:00] に取得されたものとします。
これで、[一つの完全バックアップ] と [二つのトランザクション ログバックアップ] が取得された状態となります。
最後に以下のクエリを実行して [火 18:00] 以降に追加されたデータとして挿入します。
SET NOCOUNT ON |
最後の [D] のデータはどのバックアップにも含まれていないものになります。
■障害を発生させる
[火 19:00] に発生した障害として、一度 SQL Server のサービスを停止して、[RESTORE_TEST] データベースのプライマリデータベースファイル (mdf) を破損させたいと思います。
破損ですが、バイナリエディタで mdf ファイルを開いてすべての内容を 0 で初期化しています。
# これでデータファイルには何もデータが入っていない状態となります。
この状態では、データベースがファイルとして成り立っていないため Management Studio からデータベースを展開することもできない状態となっています。
■ログ末尾のバックアップの取得
この状態になった場合、[C] のデータが入ったバックアップまではファイルとして取得されているため、既存のバックアップを使用すると、[火 18:00] の状態まではリストアすることが可能です。
[D] のデータに関しては、どのバックアップにも含まれていませんので、既存のバックアップからのリストアだけでは消失 (ロスト) するデータが出てしまいます。
このようなときに取得するのが [ログ末尾のバックアップ] (Tail log Backup) になります。
トランザクション ログが破損している場合は取得ができないのですが、データファイルが破損しておりログが正常な場合にはログ末尾のバックアップ (最後に取得したトランザクション ログのバックアップから現時点のログに含まれている内容) を取得することができます。
ログ末尾のバックアップを取得する場合のクエリは以下のようになります。
BACKUP LOG [RESTORE_TEST] |
[NO_TRUNCATE] (ログを切り捨てないで取得するバックアップ) を使用することで、ログ末尾のバックアップが取得できます。
# ログ自体が破損している場合は [CONTINUE_AFTER_ERROR] を指定することで取得できる可能性があります。
ログ末尾のバックアップと故障していますがバックアップの種別としては、通常のトランザクション ログのバックアップになります。
取得したログ末尾のバックアップをバイナリエディタで開いてみます。
[INSERT] で [DDDDDDDDDD] のデータを挿入した際に記録されたと思われるログがバックアップされているのが確認できますね。
■データベースのリストア
実際のデータベースのリストアの流れを見ていきたいと思います。
今回の環境ではリストアは以下の順番で実施します。
- MON_2200.bak をリストア
データベースが破損している状態では、Management Studio の GUI からはリストアが選択できないことがあります。このような場合は、クエリでリストアを行います。
RESTORE DATABASE [RESTORE_TEST] FROM
DISK = N’H:SQL2008R2MON_2200.bak’
WITH FILE = 1,
NORECOVERY, NOUNLOAD, REPLACE, STATS = 10 - TUE_1200.trn / TUE_1800.trn / ログ末尾のバックアップをリストア
完全バックアップのリストアができると、Management Studio の GUI からリストアができるようになります。
[msdb] の [dbo.backupset] テーブルにバックアップのレコードが残っている場合は、以下のように取得しているログのバックアップが自動的に選択されるので選択されたバックアップをリストアします。
# backupset にレコードが無い場合は、手動でバックアップを選択します。
以上でリストアは完了です。
データを確認してみると、すべてのデータを復元でき手いることが確認できます。
このようなリストアをする場合はトランザクション ログのバックアップが必要となるため、復旧モデルを [完全] または、[一括ログ] にする必要があります。
単純復旧モデルでは、トランザクション ログのバックアップを取得できないため、トランザクション ログ / ログ末尾のバックアップを利用したリストアをすることができません。
# 単純復旧モデルでは完全バックアップを取得したタイミングまでしかリストアができません。
■トランザクション ログの切り捨て
Twitter で質問があった内容なのですが、復旧モデルが [完全] [一括ログ] の場合は、トランザクション ログのバックアップを取得しないとログが蓄積された状態となります。
トランザクション ログの記録ができないと以下のエラーが発生します。
メッセージ 9002、レベル 17、状態 2、行 1 |
トランザクション ログがいっぱいになった場合、以下の方法のどちらかでトランザクション ログを切り捨てる必要があります。
- トランザクション ログのバックアップを取得
- 復旧モデルを [単純] に変更
SQL Server 2005 までは、[BACKUP LOG] を [WITH TRUNCATE_ONLY] で実行することでバックアップを取得しないでログを切り捨てることができましたが、SQL Server 2008 以降では、[TRUNCATE_ONLY] のオプションは廃止されているため使用することができません。
今回は、復旧モデルを [単純] にしてトランザクション ログの切り捨てを実行してみたいと思います。
[TEST] というデータベースのトランザクション ログをフルの状態にしてみました。
変更後に再度トランザクション ログの使用状況を確認してみます。
[Log Space Used (%)] が減っている (トランザクション ログが切り捨てられている) ことが確認できます。
SQL Server 2008 以降は [TRUNCATE_ONLY] が使えないため、バックアップの取得領域を確保できない場合には復旧モデルを変更して、ログの切り捨てを実行する必要があります。
可能な限りのデータリストアを可能とするためには [ログ末尾のバックアップ] を取得する必要がありますので、[完全] [一括ログ] のいずれかを設定しておく必要があります。
この後はデータベースのデタッチ / アタッチを使用したデータベースの移動についてのお話がありました。
次の投稿では、デタッチ / アタッチを使用したデータベースの移動についてまとめていきたいと思います。