RDS for MS SQL Server のネイティブバックアップ(完全/差分)を調べてみた

ベルリンの伊藤です。RDS for Microsoft SQL Serverのネイティブバックアップについて、お問い合わせがきっかけでその詳細を調べてみましたので、ご紹介します。

ネイティブバックアップは以前からある機能で、こちらのエントリでもやってみた手順が詳しく紹介されています。

RDS for Microsoft SQL Serverのバックアップ・リストアが簡単にできるようになりました!

RDS for SQL Server では、この機能により完全バックアップファイルや差分バックアップファイルを作成し、S3 バケットに格納することができます。

このネイティブバックアップのドキュメントに、以下のような記載があります。

差分バックアップは、最後の完全バックアップに基づいています。差分バックアップを機能させるには、最後の完全バックアップと差分バックアップの間でスナップショットを作成することはできません。差分バックアップを作成し、スナップショットが存在する場合は、差分バックアップを続行する前に別の完全バックアップを作成してください。

完全バックアップと差分バックアップとの間でスナップショットを取得してはいけないようです。

ということで差分がどのようにして取得されているのか調べてみます。

やってみた

環境の用意

まず、これらを立てます。

  • RDS インスタンス: SQL Server Express Edition 14.00.3035.2.v1 (db.t2.micro)
  • EC2 Windows インスタンス: Windows_Server-2016-English-Full-Base-2018.10.14

RDS のセキュリティグループ設定には、EC2のセキュリティグループからのインバウンド設定を。

EC2のセキュリティグループ設定には、自分の端末からのRDPのインバウンド設定を。

EC2が起動したら、リモートデスクトップでログインし、こちらから SQL Server Management Studio 17.9 をインストールします。

RDSインスタンスが利用可能になったら、インストールしたSSMSを起動して、RDSエンドポイントへログインします。
あまりにWindowsもSSMSも久しぶりで最初見つけることさえ大変でしたが、ウィンドウズキー+R→ssms ターンッでいけました。

テスト用に"testdb"というデータベースを作成してみたので、こちらでバックアップを試します。

オプショングループ設定

ネイティブバックアップには、オプショングループの設定が必要になります。

現在のDBインスタンスのオプショングループがデフォルトの場合は、新規作成します。

作成したオプションを選択して[オプションの追加]をクリックし、SQLSERVER_BACKUP_RESTORE オプションを追加します。ここでIAMロールと格納先のS3バケットを指定しますが、このタイミングで作成することもできます。ドキュメントにも具体的な手順が載ってます。

DBインスタンスの変更から作成したオプショングループを選択し、すぐに適用させます。
ちなみに再起動は発生しませんでした。

フルバックアップ & 差分バックアップの実行

早速、次のクエリを実行して完全バックアップを実行してみました。

exec msdb.dbo.rds_backup_database 
        @source_db_name='testdb',
        @s3_arn_to_backup_to='arn:aws:s3:::mi-1101-rdsbucket/full1734.bak',
        @overwrite_S3_backup_file=0,
        @type='FULL';

実行ステータスは以下で確認できます。lifecycleが「SUCCESS」で成功してますね。

exec msdb.dbo.rds_task_status @db_name='testdb';

今度は、次のクエリを実行して差分バックアップを実行しました。

exec msdb.dbo.rds_backup_database 
        @source_db_name='testdb', 
        @s3_arn_to_backup_to='arn:aws:s3:::mi-1101-rdsbucket/deff1801.bak',
        @overwrite_S3_backup_file=0,
        @type='differential';

しばらくして完了すると、S3バケットにもどちらもきちんと格納されていました。

$ aws s3 ls s3://mi-1101-rdsbucket
2018-11-01 18:02:24    1135104 deff1801.bak
2018-11-01 17:40:23    3101184 full1734.bak

スナップショット & 差分バックアップの実行

次に、コンソールからスナップショット取得します。

終わったら、再度上記の差分バックアップを実行しました。

結果発表

実行したバックアップやスナップショットは msdb.dbo.backupset テーブルで確認できるようですが、ドキュメントによると、「完全バックアップ」と「スナップショット」は type = 'D' のようですが、「差分バックアップ」はどうなの?ということで、いくつかカラムを選択して下記クエリを実行してみました。

select 
    database_name
    , backup_start_date
    , backup_finish_date 
    , type
    , recovery_model
    , is_snapshot
    , backup_size
    from    msdb.dbo.backupset 
    where   database_name='testdb'
    order by backup_start_date desc;

すると、type に大量の'L'と'I'が見られます。

backupsetテーブルに関するMSドキュメントによると、

  • D: 完全バックアップ、スナップショット
  • I: 差分スナップショット
  • L: ログ

となるようです。

また、typeが'D'のうち、is_snapshot = '1' の場合はスナップショットを示すようです。

そして、differential_base_quidで差分が基にしているバックアップIDを示していることから、簡単にSQLをまごまごして見た結果、このように差分バックアップが直前の完全バックアップまたはスナップショットを参照していることがわかりました。
赤:完全バックアップ、青:差分バックアップ、緑:スナップショット

実行SQL:

select
    a.backup_start_date
    , a.backup_finish_date
    , a.type
    , a.recovery_model
    , a.is_snapshot
    , a.backup_size
    , a.differential_base_guid
    , b.type diff_type
    , b.is_snapshot diff_snap    
    from    msdb.dbo.backupset a
    left outer join msdb.dbo.backupset b
     on a.differential_base_guid=b.backup_set_uuid
    where   a.database_name='testdb' and (a.type='I' or a.type='D')
     order by backup_start_date desc;

ちなみに、キャプチャの2,3行目にあるように差分バックアップを続けて実行した場合も、最後に実行した 'D' のバックアップをベースに行われます。

まとめ

結果としては、ドキュメントの言ってる通り、完全バックアップと差分バックアップの間にスナップショットを取得してはいけないということでした。(取得する場合は、完全バックアップを取り直さなければいけない)

非常に細かいネタでしたが、どこかの誰かに何らかの形で少しでもお役に立つと幸いです。