自動バックアップからのAzure SQL Databaseリストア設計

## はじめに

`Azure SQL Database`サービスを使う運用の場合、バックアップは原則自動バックアップを使う事になります。(自分でバックアップタイミングを指定したい場合は`BACPAC`にファイルエクスポートする手段が一番簡易なのではないかと思います）
ここでは`Azure SQL Database`のバックアップ/リストア設計をするにあたり、実際本番環境DBサーバを復旧させるにあたっての具体的手順や状況別リストア方法の選択や注意点についてまとめたいと思います。
また、本文は2019/12月時点の情報で記載しています。

各リストア手法についての概要は、別の方がまとめて下さった↓がわかりやすかったです。
[Qiita:Azure SQL Databaseリストア手法まとめ](https://qiita.com/shingo_kawahara/items/d905b6c25aafdf120444)


## 注意事項/制限事項

設計にあたって`Azure SQL Database`特有の制限事項について先にまとめておきます。特にオンプレのバックアップ、リストアと同様に考えてはいけないのが以下の点になります。

- バックアップタイミングは自分で設定できない(最短で10~15分ごと自動)
- バックアップデータの保存期間には限度がある(年1バックアップ設定で最長10年まで)
- `PointInTimeRestore`は同一サーバ内でしか復旧できない
- 復旧したDBから更に逆上って復旧させることはできない
 - DBは新規DBサービス扱いなのでバックアップデータを引き継がないから
- 既に存在するDBを上書きできない
- 復旧可能(バックアップ可能)なのはユーザDBだけでシステムDBは復旧しない
- シングルユーザモードではログインできない
 - 強制的にユーザセッションを切るみたいな操作はできない
- 単一手法でのサブスクリプション間リストアはできない(いくつか組み合わせることで実現は可能)
- トランザクション単位での復旧はできない。(指定可能なのは時間だけ)
- 復旧タイミングではDB2個分のストレージ容量が必要

バックアップデータの保持期間については、長期リテンション期間の設定(週次、月次、年次完全バックアップ)をした場合で、通常の自動バックアップの場合はプランによりますが35日が最大です。
また、メインのリストア手段である`PointInTimeRestore`は同一サーバ内にDBを復元する手法なので、別のサーバに復旧したい時は`DBCopy`を使うなど1工程手順が必要になります。
更に通常DBを復旧したい場合、同じDBを上書きして復旧する手法を想定しますが、Azureではそれはできません。なので別のDB名としてDBを復旧した後、DB名を変更して入れ替える、といった手順が必要になります。
シングルユーザモードでログインできない、についてはどうやら内部仕様的に`Azure SQL Database`は裏でレプリケーションしているようで、セッションを切断できないからのようです。

`PointInTimeRestore`の制限の仕組みについては以下が詳しかったです。
[TecBlog:Azure SQL Database の Point in Time Restore を使用したデータベースの復元方法と注意点](https://blogs.msdn.microsoft.com/jpsql/2017/06/28/sqldb_pointintimerestore/)

## 1. 最新の状態に復旧させる
最初のシナリオとして、とにかく一番最近バックアップが取れている状態に戻したい！という復旧シナリオについて考えます。この場合利用する手法としては`DBCopy`もしくは`PointInTimeRestore`から選ぶことになります。
DBCopyは最新版のバックアップデータを任意のサーバ、DBに復旧する手法、`PointInTimeRestore`は同じサーバ内に別名でDBを復旧する手法になります。　復旧をGUIから実行する場合は、このシナリオの場合どちらも特に変わりなく、`PointInTimeRestore`ではデフォルトで記入されている時刻が最新版バックアップ時刻となりますのでそのまま実行する形になります。

![database01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515252/59466c3f-07ee-4127-7fb0-0189fb658fa6.png)

しかし、Automationなどでコマンドで実装使用する場合は注意が必要で`PointInTimeRestore`を使った復旧コマンドでは時刻を入力する必要があるのですが、最新のバックアップ日付はオブジェクトの情報としては格納されていないため、これを指定してリストアすることができません。　この為コマンドで実装する場合は`DBCopy`が正直便利です。＊`DBCopy`も実際には最新版バックアップを復元しているだけなので本番DBが稼働していても特に影響を受けません。

別名DBに復旧して、アプリケーション側の接続先DB名を変更できるのであれば、上記の手順だけで完了できるのですが普通はDB名も合わせる必要があると思います。DB名は`AzurePortal`のGUI上では変更できなため、`Transact-SQL`を使って名前変更を行います。一番簡単な手法としては、適当なクライアント端末に`SQLServerManagementStudio`を導入して、`masterDB`に対してDB名変更を実施するのが良いかと思います。
`Azure SQL Database`の場合、DB名を変更するのは`MODIFY NAME`になります。
注意事項にある通り、シングルユーザモードにはできないのでアプリケーションからのセッションには注意してください。

``` DBNameChange.sql
ALTER DATABASE <OriginalDBName> MODIFY NAME = <ChangeDbName>
ALTER DATABASE <RestoreDBName> MODIFY NAME = <OriginalDBName>
```

これで、復元したDBは`<OriginalDBName>`になり、元のDBと入れ替わりました。
この後、元のDBは削除することになりますが、注意事項に記載の通り、バックアップデータを持っているのはこのDBになるので、すぐに消さずアプリケーションの動確を取ってから消すなどの運用が必要になります。
でないと、復元したタイミングですでにおかしい場合、更に前には戻せなくなっているからです。
ちなみにDBの削除はGUIからリソースの削除と同様の手順で削除可能です。

DBの復旧手順については以下を参考にしました。
[MS:自動データベース バックアップを使用して Azure SQL データベースを復旧する](https://docs.microsoft.com/ja-jp/azure/sql-database/sql-database-recovery-using-backups)
[MS:データベースの名前変更](https://docs.microsoft.com/ja-jp/sql/relational-databases/databases/rename-a-database?view=sql-server-ver15)

DBCopyについては以下を参考にしています。
[MS:トランザクション上一貫性のある Azure SQL データベースのコピーを作成する](https://docs.microsoft.com/ja-jp/azure/sql-database/sql-database-copy)

## 2. 任意のタイミングに復旧させる
一番想定されるシナリオだと思いますが、この場合は`PointInTimeRestore`か長期バックアップ保管から選ぶことになるかと思います。　この場合リストア手法としては復元一択となるため、どのバックアップデータを利用するかだけの検討となりますが、`PointInTimeRestore`が標準機能として無料であるのに対して長期バックアップ保管は有料のオプションになります。長期バックアップ保管からリストアする場合は復元メニューで「特定の時点」から「長期バックアップ保管」を選ぶだけです。

![database02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515252/eb894721-395c-d540-3ec8-53849a3aadd0.png)

考慮点としては、最大値で考慮する場合、35日前までは分単位でリストア可能だが、35日以降は細かくても週次単位でしか戻せない(しかも追加料金)という点になります。

復旧手段は1.とまったく同じなので省略！

長期バックアップリテンションについては以下に詳細が載ってます
[MS:最大で 10 年間 Azure SQL Database のバックアップを格納する](https://docs.microsoft.com/ja-jp/azure/sql-database/sql-database-long-term-retention)

## 3. BCP拠点からの復旧
もし、本番DB環境で利用しているリージョンのDCサイトが災害等にあって完全につぶれてしまった場合、別のリージョンでシステムを再構築してDBを復旧させたい！の要件の時に利用する方法になります。手法としては「Geoレプリケーション」を利用した別リージョンへのDBリストアです。「Geoレプリケーション」は有料オプションになりますがDBを複数リージョンに跨りフェールオーバ構成ができるサービスです。　リソース全体をリージョン間でフェールオーバできる構成にしている場合はサイトに障害が発生した時、そのまま全構成がフェールオーバしてすぐさま別リージョンでサービスが復旧する仕組みですが、DBだけBCP的な形で遠隔地バックアップしておきたい要件の時にも利用できます。

「Geoレプリケーション」からDBを復元する場合は、復旧する対象のリージョンでDBサーバを構築した後、DB作成時に「ソースの選択」で「バックアップ」を選択することで同じサブスクリプション内でレプリケートされたDBのバックアップを選択することができます。

![database03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515252/0910c575-c31d-c4fa-650e-23a44f151bdd.png)

こちらは要件はないと思いますが、復旧時点はDBCopyと同じく最新のバックアップ時点のみとなります。

Geoレプリケーションについては↓の方に詳細があります。
[MS:アクティブ geo レプリケーションの作成と使用](https://docs.microsoft.com/ja-jp/azure/sql-database/sql-database-active-geo-replication)
Geoレプリケーションを利用したリストアは「Geoリストア」として↓に詳細があります。
[MS:自動データベース バックアップを使用して Azure SQL データベースを復旧する](https://docs.microsoft.com/ja-jp/azure/sql-database/sql-database-recovery-using-backups)

## おわりに
基本的な運用として考慮するDBのリストア手法についてはこんなものかなと思います。オンプレのインフラ屋さん的には「制限多いなぁ」という印象で特にDBに上書きでリストアできないあたり、最初衝撃が走ったのですが、クラウド屋さん的にはそうでもないのでしょうか？？
今回のリストア手法に関してはAutomationを使った自動化を進めていますので、そちらも出来上がったら記事にしようと思います。