Azure SQL Database地理レプリケーション完全ガイド!DR対策とBCP策定のポイント
生徒
「Azure(アジュール)でデータベースを使っているのですが、もしデータセンターが災害で止まったらデータはどうなるんですか?」
先生
「それは非常に重要な視点ですね。クラウドといえども、物理的な故障や自然災害のリスクはゼロではありません。そこで役立つのが『地理(ちり)レプリケーション』という機能です。」
生徒
「地理レプリケーションを使うと、遠く離れた場所にデータのコピーを作れると聞いたのですが、設定は難しいのでしょうか?」
先生
「実はAzure SQL Database(アジュール・エスキューエル・データベース)なら、比較的簡単に設定できますよ。今日は災害対策(さいがいたいさく)や事業継続計画(じぎょうけいぞくけいかく)の基本から、具体的な活用方法まで一緒に学んでいきましょう!」
1. 地理レプリケーションとは?
Azure SQL Databaseの地理レプリケーション(Geo-Replication)とは、メインで利用しているデータベース(プライマリ)のデータを、別の地域(リージョン)にあるデータベース(セカンダリ)へリアルタイムに近い形でコピーし続ける機能のことです。例えば、東日本リージョンにあるデータを、数百キロ離れた西日本リージョンに自動でバックアップしておくような仕組みを指します。
この機能の最大の特徴は、万が一メインの地域が地震や停電などでダウンしても、別の地域にあるコピーを使ってシステムを動かし続けられる点にあります。これをITの世界ではDR(Disaster Recovery:ディザスタリカバリ/災害復旧)と呼びます。また、企業が災害時でもビジネスを止めないための計画をBCP(Business Continuity Plan:ビジネス継続計画)と言い、地理レプリケーションはその中核を担う技術です。
2. リージョンとペアリングの重要性
Azureには世界中に「リージョン」と呼ばれるデータセンターの拠点があります。日本には「東日本」と「西日本」があり、これらはリージョンペアとして定義されています。地理レプリケーションを設定する際は、このペアを利用するのが一般的です。なぜなら、ペア間は高速なネットワークで結ばれており、かつ十分な距離が離れているため、広域災害の影響を同時に受けにくいからです。
地理レプリケーションには「アクティブ地理レプリケーション」という種類があり、読み取り専用のセカンダリデータベースを最大4つまで作成できます。これにより、災害対策だけでなく、世界各地のユーザーに近い場所からデータを読み取らせることで、アプリのレスポンスを向上させる「負荷分散(ふかぶんさん)」にも活用されています。
3. 地理レプリケーションの設定状態を確認する
まずは、現在のデータベースがどのようなレプリケーション状態にあるかをSQLで確認してみましょう。システムビューを参照することで、同期の状態やロール(主か副か)を把握できます。管理者は定期的にこの状態をチェックすることが推奨されます。
SELECT
partner_server,
partner_database,
replication_state_desc,
role_desc,
secondary_allow_connections_desc
FROM sys.dm_geo_replication_link_status;
このクエリを実行した結果の例を以下に示します。通常時はメイン側が「PRIMARY」、コピー側が「SECONDARY」と表示されます。
partner_server | partner_database | replication_state_desc | role_desc | secondary_allow_connections_desc
---------------+------------------+------------------------+-----------+---------------------------------
sql-secondary | my-db-replica | CATCH_UP | PRIMARY | ALL
4. フェールオーバーとBCP策定のベストプラクティス
もしメインのデータベースが利用不能になった場合、手動または自動でセカンダリをプライマリに昇格させる操作をフェールオーバーと呼びます。BCPを策定する上では、以下の2つの指標を明確に決めておく必要があります。
- RPO(Recovery Point Objective:目標復旧時点):どの時点のデータまで戻すか(地理レプリケーションでは通常5秒未満のデータ損失に抑えられます)。
- RTO(Recovery Time Objective:目標復旧時間):どれくらいの時間で復旧させるか(接続の切り替えにかかる時間など)。
ベストプラクティスとしては、個別のデータベースごとに切り替えるのではなく、複数のデータベースをまとめて管理できる「オートフェールオーバーグループ」という機能を使うことが推奨されます。これにより、接続文字列を変更することなく、DNSレベルで自動的に接続先を切り替えることが可能になります。
5. C#からセカンダリデータベースへ接続する方法
読み取り専用のセカンダリデータベースを活用することで、メインのデータベースの負荷を軽くすることができます。例えば、集計レポートの作成やデータの閲覧だけなら、セカンダリに接続すれば十分です。C#のプログラムから接続する場合、接続文字列にオプションを追加するだけで簡単に実現できます。
using System;
using Microsoft.Data.SqlClient;
class Program
{
static void Main()
{
// ApplicationIntent=ReadOnlyを指定することで読み取り専用レプリカに接続
string connectionString = "Server=tcp:my-sql-server.database.windows.net;Initial Catalog=my-db;User ID=admin;Password=password;ApplicationIntent=ReadOnly;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
Console.WriteLine("読み取り専用レプリカに接続しました。");
string sql = "SELECT COUNT(*) FROM Inventory";
SqlCommand command = new SqlCommand(sql, connection);
int count = (int)command.ExecuteScalar();
Console.WriteLine($"現在の在庫数: {count}");
}
}
}
読み取り専用レプリカに接続しました。
現在の在庫数: 1540
6. Azure CLIを使用したレプリカ作成の自動化
インフラの構築を手作業で行うとミスが発生しやすいため、コマンドライン(Linux環境など)から自動化するのが一般的です。Azure CLI(アジュール・シーエルアイ)を使えば、一行のコマンドで別のリージョンにセカンダリデータベースを作成できます。
az sql db replica create --name my-db --partner-server sql-secondary --resource-group my-rg --server sql-primary
Creating secondary replica for database 'my-db'... Done.
このように、スクリプト化しておくことで、災害発生時に環境を素早く再構築したり、開発環境を本番に近い構成で立ち上げたりすることが容易になります。これがInfrastructure as Code(IaC:インフラストラクチャ・アズ・コード)の第一歩です。
7. データの整合性と同期の仕組み
地理レプリケーションは「非同期(ひどうき)」でデータを転送します。これは、メイン側の処理を止めずに、バックグラウンドでこっそりデータを送る仕組みです。そのため、メインで書き込みが完了した直後に災害が起きると、数秒分のデータがコピー先に届いていない可能性があります。しかし、多くのビジネスシーンでは、システムが完全に止まってしまうよりは、数秒前のデータで再開できる方がメリットが大きいと判断されます。
以下のテーブルは、ある店舗管理システムの「在庫テーブル(Inventory)」の例です。メインとセカンダリでデータがどのように同期されているかイメージしてみましょう。
product_id | product_name | stock_count | last_updated
-----------+--------------+-------------+-------------------
101 | ゲーミングPC | 5 | 2026-03-31 10:00
102 | 4Kモニター | 12 | 2026-03-31 10:05
103 | 無線マウス | 45 | 2026-03-31 10:10
104 | 有線キーボード | 28 | 2026-03-31 10:15
ここで、新しい商品を追加するSQLを実行してみます。
INSERT INTO Inventory (product_id, product_name, stock_count, last_updated)
VALUES (105, 'Webカメラ', 15, '2026-03-31 10:20');
実行後のテーブル状態は以下のようになり、この変更が数秒以内に別リージョンのセカンダリにも反映されます。
product_id | product_name | stock_count | last_updated
-----------+--------------+-------------+-------------------
101 | ゲーミングPC | 5 | 2026-03-31 10:00
102 | 4Kモニター | 12 | 2026-03-31 10:05
103 | 無線マウス | 45 | 2026-03-31 10:10
104 | 有線キーボード | 28 | 2026-03-31 10:15
105 | Webカメラ | 15 | 2026-03-31 10:20
8. 地理レプリケーションのコストと注意点
非常に便利な機能ですが、コスト面には注意が必要です。セカンダリデータベースも、メインと同じスペックの計算リソース(DTUや仮想コア)を消費するため、単純計算でデータベース利用料が2倍になります。また、リージョン間をまたぐデータ転送量(アウトバウンド通信)にも課金が発生します。
コストを最適化するためには、本番環境では高スペックなレプリカを用意し、開発やテスト環境では地理レプリケーションをオフにする、といった運用上の工夫が必要です。また、セカンダリ側のデータベースのスペックが低すぎると、メインからのデータ転送に追いつけず「遅延(ラグ)」が発生し、災害時の復旧に支障をきたすことがあるため、基本的には同じサイズに設定するのがセオリーです。
9. 地理冗長バックアップとの違いを理解する
Azure SQL Databaseには、標準で「地理冗長バックアップ(RA-GRS)」という機能も備わっています。これは安価ですが、復旧にはバックアップデータからのリストア(復元)が必要なため、数時間以上の時間がかかることがあります。一方で、地理レプリケーションは常にデータベースが「起動した状態」で待機しているため、数分での切り替えが可能です。
金融システムやECサイトなど、一分一秒の停止も許されないシステムでは地理レプリケーションを選択し、社内向けのそれほど急ぎではないツールであればバックアップ機能のみで済ませる、といった使い分けが重要です。クラウドの利点を最大限に活かすためには、システムの重要度に応じたDR対策を設計することが、真のBCP策定と言えるでしょう。
まとめ
今回の記事では、Azure SQL Databaseの地理レプリケーションについて、その基礎知識から具体的な設定、運用におけるポイントまで詳しく解説してきました。大規模な災害やシステム障害が発生した際、ビジネスを継続させるためのBCP(事業継続計画)やDR(災害復旧)対策は、現代のITシステムにおいて欠かせない要素です。地理レプリケーションを活用することで、メインのリージョンとは別の物理的な場所にデータのコピーをリアルタイムで保持し、万が一の事態にも迅速に対応できる体制を整えることができます。
特に、東日本と西日本のリージョンペアを利用した冗長化は、ネットワークの遅延を抑えつつ、広域災害のリスクを分散させる非常に有効な手段です。また、アクティブ地理レプリケーションを利用すれば、読み取り専用のセカンダリデータベースを最大4つまで作成できるため、災害対策だけでなく、読み取り負荷の分散によるシステム全体のパフォーマンス向上にも寄与します。C#などのプログラムから接続する際も、接続文字列にオプションを追加するだけで読み取り専用レプリカを活用できる柔軟性は、開発者にとっても大きなメリットと言えるでしょう。
運用面では、RPO(目標復旧時点)やRTO(目標復旧時間)といった指標を明確に定め、オートフェールオーバーグループなどの機能を組み合わせて、自動的な切り替えができるように設計することが推奨されます。コスト面や同期の仕組み(非同期転送)によるわずかなデータ損失の可能性など、注意すべき点はいくつかありますが、システムの重要度に応じて適切なプランを選択することが大切です。Azure CLIなどのツールを用いた自動化も積極的に取り入れ、ミスのない確実なインフラ構築を目指しましょう。
実践的な確認とコードの振り返り
ここで、実際に運用で使われるSQLやC#のコード、そしてデータの状態がどのように変化するかを、改めておさらいしておきましょう。まずはデータベースのレプリケーション状態を確認するSQLです。
SELECT
link_guid,
partner_server,
partner_database,
last_replication,
replication_state_desc,
role_desc
FROM sys.dm_geo_replication_link_status;
このクエリを実行することで、現在どのサーバーがプライマリ(主)で、どのサーバーがセカンダリ(副)として動いているか、そして同期が正常に行われているかを確認できます。
link_guid | partner_server | partner_database | last_replication | replication_state_desc | role_desc
-------------------------------------+----------------+------------------+---------------------+------------------------+----------
a1b2c3d4-e5f6-7890-abcd-ef1234567890 | sql-secondary | my-db-replica | 2026-03-31 13:40:05 | CATCH_UP | PRIMARY
次に、ビジネス継続において重要なデータの同期イメージを確認します。例えば、顧客の注文情報を管理する「Orders」テーブルがあるとします。
order_id | customer_name | amount | status | created_at
---------+---------------+--------+------------+-------------------
5001 | 佐藤次郎 | 12000 | PAID | 2026-03-31 13:00
5002 | 鈴木花子 | 8500 | PENDING | 2026-03-31 13:10
5003 | 田中一郎 | 3200 | SHIPPED | 2026-03-31 13:20
5004 | 伊藤美咲 | 15000 | PAID | 2026-03-31 13:30
新しい注文が入った際に、プライマリデータベースで以下のSQLを実行します。
INSERT INTO Orders (order_id, customer_name, amount, status, created_at)
VALUES (5005, '高橋健太', 5400, 'PAID', '2026-03-31 13:40');
この変更は、地理レプリケーションによって数秒以内にセカンダリデータベースへ反映されます。反映後のテーブルは以下のようになります。
order_id | customer_name | amount | status | created_at
---------+---------------+--------+------------+-------------------
5001 | 佐藤次郎 | 12000 | PAID | 2026-03-31 13:00
5002 | 鈴木花子 | 8500 | PENDING | 2026-03-31 13:10
5003 | 田中一郎 | 3200 | SHIPPED | 2026-03-31 13:20
5004 | 伊藤美咲 | 15000 | PAID | 2026-03-31 13:30
5005 | 高橋健太 | 5400 | PAID | 2026-03-31 13:40
また、開発現場ではLinux環境からAzure CLIを使用して、レプリカの削除や管理を行うこともあります。以下は、不要になったレプリカ接続を解除する際のコマンド例です。
az sql db replica delete --name my-db --resource-group my-rg --server sql-secondary --yes
Deleting replica connection for database 'my-db'... Done.
最後に、C#アプリケーションからデータベースへ接続し、現在のロール(役割)が何であるかを確認するプログラムの例を紹介します。
using System;
using Microsoft.Data.SqlClient;
class CheckRoleProgram
{
static void Main()
{
// 接続文字列の設定
string connStr = "Server=tcp:my-sql-server.database.windows.net;Initial Catalog=my-db;User ID=admin;Password=password;";
using (SqlConnection connection = new SqlConnection(connStr))
{
try
{
connection.Open();
Console.WriteLine("データベースへの接続に成功しました。");
// 現在のロールを確認するクエリ
string sql = "SELECT DATABASEPROPERTYEX('my-db', 'Updateability')";
SqlCommand command = new SqlCommand(sql, connection);
string result = (string)command.ExecuteScalar();
if (result == "READ_WRITE")
{
Console.WriteLine("このデータベースは『書き込み可能(プライマリ)』です。");
}
else
{
Console.WriteLine("このデータベースは『読み取り専用(セカンダリ)』です。");
}
}
catch (Exception ex)
{
Console.WriteLine($"エラーが発生しました: {ex.Message}");
}
}
}
}
データベースへの接続に成功しました。
このデータベースは『書き込み可能(プライマリ)』です。
生徒
「先生、地理レプリケーションについて詳しく教えていただきありがとうございました!東日本と西日本でデータを同期させることで、もしもの時も安心できるということがよく分かりました。」
先生
「その通りですね。特に『非同期』でデータが送られているという点は理解できましたか?メインの処理を遅らせないための工夫ですが、わずかなタイムラグがあることは覚えておきましょう。」
生徒
「はい!だからこそRPO(目標復旧時点)を何秒にするか、という設計が大事なんですね。あと、読み取り専用のセカンダリを普段から活用できるのも、リソースの無駄がなくて良いなと思いました。」
先生
「素晴らしい気づきです。コストはかかりますが、それを単なるバックアップとして眠らせておくのではなく、レポート作成やデータ分析に使うことで、システム全体の効率を上げられますからね。」
生徒
「C#のプログラムでも、接続文字列に『ApplicationIntent=ReadOnly』を入れるだけで使い分けられるのは便利ですね。さっそく自分のアプリでも試してみたいと思います!」
先生
「ぜひ試してみてください。Azure CLIを使った自動化も、将来的に大規模なシステムを運用する際には必ず役に立ちますよ。エラー処理も含めて、少しずつマスターしていきましょうね。」
生徒
「ありがとうございます。BCP策定についても、会社のチームでも話し合ってみようと思います。クラウドを使いこなして、止まらないシステムを作れるエンジニアを目指します!」
先生
「その意気です。技術は日々進化していますが、データの安全を守るという基本は変わりません。これからも一緒に頑張りましょう!」