Azure SQL Database(Hyperscale)で数百 GB クラスの本番 DB を運用していると、「別サブスクリプション・別テナントへどうやって速く安全にコピーするか」は現場で必ず出てくるテーマです。この記事では、BACPAC では 10 時間以上かかる 600GB 級 DB を、ダウンタイムを抑えつつ別テナントへ移行するための現実的な手順と設計の考え方を、具体的な T‑SQL 例とともに整理します。
シナリオと前提条件の整理
想定シナリオ
今回取り上げるのは、次のようなケースです。
- Azure SQL Database(Hyperscale、約 600GB)を本番トランザクション DB として利用中
- コピー先は「別サブスクリプション」かつ「別の Microsoft Entra ID(旧 Azure AD)テナント」
- BACPAC(エクスポート → インポート)だと 10 時間以上かかり、ダウンタイムも大きくなる
- できるだけ短時間で、安全にクロステナント移行したい
結論から言うと、この条件で「速くて安定」なのは、T‑SQL と SQL 認証を使ったサービス側のデータベースコピー、もしくはアクティブ geo レプリケーションを使ったフェールオーバー方式です。Azure SQL の公式ドキュメントでも、クロスサブスクリプション/クロステナントのコピーや geo レプリケーションは、SQL 認証+T‑SQL/REST API のみサポートと明記されています。
この記事での前提
- ソース/ターゲットともに Azure SQL Database(PaaS、Hyperscale)
- 両方ともネットワーク的にインターネット(Public Endpoint)経由で到達可能
- Private Endpoint はあってもよいが、コピー/geo レプリケーション開始時は一時的に Public アクセスを許可できる
- Azure Portal / Azure CLI だけで完結させるのではなく、SQL Server Management Studio(SSMS)や Azure Data Studio などから T‑SQL を実行できる
移行方式の比較:何を選ぶべきか
まずは代表的な 3 つの方式をざっくり比較します。
| 方式 | クロステナント対応 | 速度の傾向 | 停止時間(カットオーバー) | 主な用途 |
|---|---|---|---|---|
| BACPAC(エクスポート/インポート) | ○(どこへでも持っていける) | データサイズ依存。600GB クラスだと数時間〜十数時間も珍しくない | エクスポート・インポートの間は基本オフライン前提 | 最終手段。スキーマ変更やバージョン変換を兼ねたいとき |
| サービス側コピー (CREATE DATABASE … AS COPY OF) | ○(T‑SQL+SQL 認証のみ) | Hyperscale 同一リージョンなら Fast copy で非常に高速。別リージョンは size-of-data コピーで時間増加 | コピー完了までソースはオンライン。切替時のみ短時間停止 | 本番 DB を丸ごと別テナントへコピーしたい場合の第一候補 |
| アクティブ geo レプリケーション | ○(T‑SQL+SQL 認証のみ) | 同期中は継続的にログを転送。初期シーディングは DB サイズに応じた時間 | 最小化可能(数十秒〜数分レベルまで抑えやすい) | 停止時間を極限まで短くしたい場合のベストプラクティス |
このうち、「速さ」と「シンプルさ」のバランスが良いのがサービス側コピーです。アクティブ geo レプリケーションはさらにダウンタイムを削れますが、構成管理の手間が少し増えます。
最有力案:T‑SQL+SQL 認証による「データベース コピー」
機能のポイント
Azure SQL Database の CREATE DATABASE … AS COPY OF を使うと、サービス側(プラットフォーム側)で DB のクローンを作成できます。
- ソース DB はオンラインのままコピー(読み書き継続可能)
- コピー完了後は完全に独立した DBになる(バックアップや SLO も別管理)
- Hyperscale の場合、同一リージョンならスナップショットベースの Fast copyとなり、サイズにあまり依存せず高速
- 別リージョンやバックアップ冗長性が異なる場合は、size-of-data コピーとなり、データ量に応じた時間がかかる
- 内部的には geo レプリケーション技術を使ってシーディングし、完了後にリンクを自動的に切断する
そして重要なのは、公式ドキュメントに次のような制約が明記されている点です。
- 別テナントのサブスクリプションに対する DB コピーは、T‑SQL+SQL 認証でのみサポート
- Microsoft Entra ID 認証のみでは別テナントへのコピーは不可
- T‑SQL による DB コピーは、Private Endpoint 経由の接続ではサポートされない(Public IP から接続して実行する必要がある)
つまり、クロステナント移行をしたいなら、「ターゲット側サーバーに SQL ログインで接続 → T‑SQL で CREATE DATABASE … AS COPY OF を実行」というスタイルが必須になります。
Hyperscale で高速になる理由
Hyperscale では、コンピュートとストレージが分離されたアーキテクチャになっており、ストレージ層はスナップショットとログの組み合わせで構成されています。 そのため、同一リージョンへのコピーでは、巨大な 600GB DB でも「ストレージスナップショットの複製」ベースで処理されるため、一般的なフルバックアップ/リストアと比べて圧倒的に速くなります。
別リージョンコピーの場合は、ページサーバー上の BLOB を並列コピーする「size-of-data コピー」となり、データ量やネットワーク帯域に応じて数時間単位の時間がかかる可能性があります。ただし、ページごとに並列コピーされるため、コピー時間が完全にサイズに比例するわけではありません。
手順詳細:別テナントへの Azure SQL Database コピー
ここからは、実際に別テナントの Azure SQL サーバーへ DB をコピーする手順を、具体的な T‑SQL 付きで説明します。
全体の流れ
- ソース/ターゲット両サーバーのファイアウォール設定
- ソース側で SQL ログインとユーザー作成(SID を控える)
- ターゲット側で同じ SID を持つログイン/ユーザー作成
- ターゲット側 master に接続し、CREATE DATABASE … AS COPY OF を実行
- DMV でコピー進捗を監視、完了後に検証
事前準備:ファイアウォールと Private Endpoint
まず、T‑SQL によるコピーには次の条件があります。
- ソース/ターゲット両サーバーのファイアウォールで、コピー操作を実行するクライアント IP を許可する必要がある
- Private Endpoint 経由では T‑SQL コピーはサポートされない
→ Public access が許可されている状態で、Public IP から接続して実行する必要がある - コピー完了後は、Public access を再度無効化してよい
自分がどの IP から接続しているかは、次のクエリで確認できます。
SELECT client_net_address
FROM sys.dm_exec_connections
WHERE session_id = @@SPID;
ステップ 1:ソース側で SQL ログインとユーザーを作成
ソースサーバー(コピー元)の master で、コピー専用の SQL ログインを作成します。
-- ソースサーバーの master に接続して実行
USE master;
GO
CREATE LOGIN dbcopyuser WITH PASSWORD = '強力なパスワードを設定してください';
GO
CREATE USER dbcopyuser FOR LOGIN dbcopyuser;
GO
ALTER ROLE dbmanager ADD MEMBER dbcopyuser;
GO
続いて、コピー元 DB 上で dbcopyuser に db_owner を付与します。
-- コピー元データベース上で実行
USE [SourceDb];
GO
CREATE USER dbcopyuser FOR LOGIN dbcopyuser;
GO
ALTER ROLE db_owner ADD MEMBER dbcopyuser;
GO
最後に、このログインの SID を控えておきます。Tech Community のクロステナントコピー手順でも、SID をそろえることが推奨されています。
SELECT name, sid
FROM sys.sql_logins
WHERE name = 'dbcopyuser';
ステップ 2:ターゲット側で同じ SID を持つログインを作成
次に、ターゲットサーバー(別テナント)の master で、控えた SID を使ってログインを作成します。
-- ターゲットサーバーの master に接続して実行
USE master;
GO
CREATE LOGIN dbcopyuser
WITH PASSWORD = 'ソースと同等の強力なパスワード',
SID = 0x… -- ソースで確認した SID をそのまま貼り付け
GO
CREATE USER dbcopyuser FOR LOGIN dbcopyuser;
GO
ALTER ROLE dbmanager ADD MEMBER dbcopyuser;
GO
このようにしておくと、コピーされた DB 内のユーザーとログインの紐付けが崩れず、権限周りの手直しが最小限で済みます。
ステップ 3:ターゲット側 master に接続してコピーを開始
いよいよ DB コピーを開始します。ポイントは、ターゲットサーバーの master に SQL 認証で接続し、そこで CREATE DATABASE を実行することです。
-- ターゲットサーバーの master に dbcopyuser で接続して実行
USE master;
GO
CREATE DATABASE [NewDb]
AS COPY OF [sourceServerName].[SourceDb];
GO
sourceServerNameにはservername.database.windows.netの servername 部分のみを指定します。- Hyperscale DB の場合、サービス目標(
HS_Gen5_4など)は基本的にソースと同じになりますが、必要に応じてSERVICE_OBJECTIVE句で上げておくと、シーディングが安定しやすくなります。
性能的な安全策としては、コピー時はソースと同等以上の SLO にしておき、完了後に落とすのがおすすめです。
ステップ 4:コピー進捗の監視
コピー開始後は、次の DMV で進捗を監視できます。
-- データベースの状態確認
SELECT name, state_desc
FROM sys.databases
WHERE name = 'NewDb';
-- コピーの詳細(進捗率など)
SELECT database_id, start_date, percent_complete,
partner_server, partner_database, replication_state_desc
FROM sys.dm_database_copies
WHERE database_id = DB_ID('NewDb');
-- 操作全体の状態
SELECT *
FROM sys.dm_operation_status
WHERE major_resource_id = 'NewDb';
sys.databasesのstate_descがCOPYING→ONLINEになればコピー完了sys.dm_database_copiesの行は、コピー完了時に自動的に削除される
Hyperscale の同一リージョン Fast copy では、600GB クラスでも「思ったより早く終わる」ことが多いので、本番切替前に試行コピーで実測しておくと安心です。
ステップ 5:完了後の確認と仕上げ
コピーが完了したら、少なくとも次の点はチェックしておきましょう。
- アプリケーションからターゲット DB への疎通テスト(接続文字列の変更を含む)
- 読み書き系の代表的なトランザクションを実行して動作確認
- ログイン/ユーザーの整合性(孤立ユーザーがいないか)
- 必要に応じて
DBCC CHECKDBの実行 - コピー時に上げていた SLO を本来のサイズに戻す
Hyperscale 特有のポイント:コピー時間の考え方
Fast copy と size-of-data コピー
Hyperscale では、ターゲットの条件によってコピー方式が切り替わります。
| パターン | 条件 | コピー方式 | 時間の傾向 |
|---|---|---|---|
| Fast copy | ソースと同一リージョンかつバックアップ冗長性が同じ | ストレージスナップショットを利用した高速コピー | DB サイズにあまり依存せず高速(数百 GB でも数十分〜程度で終わることが多い) |
| size-of-data コピー | ターゲットが別リージョン、またはバックアップ冗長性(LRS / ZRS / GRS)が異なる | ページサーバー BLOB の並列コピー | データ量・ネットワーク帯域に応じて数時間かかることもある |
600GB クラスの DB でも、同一リージョン内であれば Fast copy を優先する設計にすると、コピー時間をかなり抑えられます。
サービス目標(SLO)の選び方
コピー中は、ターゲット側で大量の I/O とログ適用が発生します。そのため Microsoft のドキュメントでも、コピー先を極端に低い性能にしないことが推奨されています。
- コピー時:ソースと同等か、やや高めの SLO(vCore / DTU)
- コピー完了後:負荷を見ながら段階的に縮小
特に Hyperscale ではコンピュートを柔軟にスケールできるので、コピーの前後だけ一時的にスケールアップする運用を検討するとよいでしょう。
ダウンタイムを最小化する案:アクティブ geo レプリケーション
アクティブ geo レプリケーションとは
アクティブ geo レプリケーションは、トランザクションログを非同期に複製し続けるセカンダリ DB を別リージョンや別サーバーに作る機能です。
- 最大 4 つのセカンダリを作成可能
- 通常は数秒以内の遅延で同期(完全ゼロではない)
- フェールオーバーすると、セカンダリがプライマリに昇格
- 主な用途は DR(障害対策)だが、DB 移行にも推奨されている
この仕組みを応用すると、書き込みをほぼ止めずに別テナントへ DB を移行することができます。
クロステナントでのサポート範囲
アクティブ geo レプリケーションも、コピーと同じく次の制約があります。
- Azure Portal からの構成は、同一テナント内のサブスクリプション間のみ
- 別テナントのサブスクリプションにセカンダリを作る場合は、SQL 認証+T‑SQL で構成する必要がある
- Microsoft Entra ID 認証のみが有効なサーバーでは、クロスサブスクリプション/クロステナントの geo レプリケーションはサポートされない
- Private Endpoint 経由での T‑SQL によるセカンダリ作成はサポートされない(Public IP 経由で一度だけ構成し、その後 Public access を閉じる)
また、Microsoft Q&A でも、別テナント間のアクティブ geo レプリケーションはサポートされていることが、Azure サポートから公式に回答されています。
構成の典型的な手順
手順のパターン自体は DB コピーとよく似ています。
- ソース/ターゲット両サーバーに geo レプリケーション用の SQL ログイン(例:
geodrsetup)を作成し、dbmanagerを付与 geodrsetupの SID をソース/ターゲットで合わせる- ソース側の master に
geodrsetupで接続し、ALTER DATABASE … ADD SECONDARY ON SERVERを実行 sys.dm_geo_replication_link_statusやsys.dm_operation_statusでシーディング状態を監視- 同期完了後、メンテナンスウィンドウで
ALTER DATABASE … FAILOVERによる計画フェールオーバー
T‑SQL のイメージは次のようになります(基本構文)。
-- ソースサーバーの master に geodrsetup で接続して実行
USE master;
GO
ALTER DATABASE [SourceDb]
ADD SECONDARY ON SERVER [targetServerName]
WITH (ALLOW_CONNECTIONS = ALL);
GO
-- 進捗確認(ソース DB 上)
SELECT * FROM sys.dm_geo_replication_link_status
WHERE database_id = DB_ID('SourceDb');
SELECT * FROM sys.dm_operation_status
WHERE major_resource_id = 'SourceDb';
計画フェールオーバー時には、ターゲット側で次のように実行します。
-- ターゲットサーバー(セカンダリ)で master に接続して実行
ALTER DATABASE [SourceDb] FAILOVER;
GO
フェールオーバー後は、必要に応じて元のプライマリサーバーをセカンダリにするか、REMOVE SECONDARY ON SERVER でリンクを切断し、移行完了とすることができます。
大容量で BACPAC を使う場合の工夫
基本的にはサービス側コピー/geo レプリケーションを推奨しますが、要件によっては BACPAC を使わざるを得ないケースもあります。その場合、どれだけ「速く・安全に」BACPAC を動かせるかが勝負になります。
パフォーマンスを出すためのベストプラクティス
Microsoft の SQLPackage ガイドやサポートブログでは、大容量 BACPAC のパフォーマンス改善策として次のポイントが紹介されています。
- エクスポート/インポートを行う VM は、DB と同一リージョンに配置する
- VM は十分な CPU / メモリと 高速ディスク(Premium SSD / NVMe) を持つサイズを選ぶ
- SQL Database 側は、エクスポート/インポート中だけ Business Critical や Premium レベル に一時的にスケールアップする
- VM で 加速ネットワーク(Accelerated Networking) を有効化する
- ストレージは Premium / 高スループットなストレージアカウントを利用する
また、最近は Import/Export に対しても Private Link がサポートされており、セキュアな経路を確保したまま BACPAC を実行することもできます。
とはいえ、600GB クラスの DB では、これらの対策をしても数時間〜十数時間かかることが多いため、「どうしてもスキーマ変換などの理由で BACPAC が必要」な場合の最終手段として位置付けるのがおすすめです。
カットオーバー戦略の例
方式 A:サービス側コピーを使うシンプルな切替
ダウンタイムを「短め」に抑えたいが、ゼロにこだわらない場合の現実的なパターンです。
- 事前に試行コピーを 1 回実行し、600GB DB のコピー所要時間の目安を取る
- 本番切替のメンテナンスウィンドウを決める(例:深夜 2 時〜4 時)
- メンテナンス開始直前に、アプリケーションの書き込みを停止(読み取り専用にするかメンテナンスページへ切替)
- ソース DB 上で最後の整合性確認(キューやバッチが空など)をしてから、本番用のコピーを開始
sys.databasesやsys.dm_database_copiesでコピー完了を確認- ターゲット DB で疎通確認・クエリのスポットチェックを実施
- アプリケーションの接続文字列をターゲットサーバー/DB に切り替え、本番トラフィックを受ける
この方式では、実質的な停止時間は「書き込み停止〜ターゲットでの疎通確認完了」までの間のみとなり、数十分〜程度に抑えられるケースが多いです。
方式 B:アクティブ geo レプリケーションで停止時間を極小化
止められるのは数分以内が限界というような要件の場合は、アクティブ geo レプリケーションによる切替が有効です。
- 平常時に、別テナントのターゲットサーバーへ geo セカンダリを構成(SQL 認証+T‑SQL)
- シーディング完了後、しばらく本番運用しながらレプリケーション遅延や負荷を監視
- メンテナンスウィンドウ直前に、アプリケーションを「書き込みほぼゼロ」の状態まで落とす(キュー停止など)
- ターゲット側で
ALTER DATABASE … FAILOVERを実行し、DB の役割を入れ替える - アプリケーションの接続文字列をターゲットサーバーに切り替え、本番再開
- 十分な期間稼働を確認したら、元のサーバーとの geo レプリケーションリンクを削除
この方式では、停止時間はほぼ「フェールオーバー+アプリ再起動分」に限定でき、数十秒〜数分で収まることも十分可能です。
実運用での落とし穴とベストプラクティス
Private Endpoint と Public access の扱い
セキュリティ要件が厳しい環境では、Azure SQL を Private Endpoint のみで公開しているケースも多いと思いますが、DB コピーや geo レプリケーション構成時には Public access が必要な点に注意が必要です。
- 構成時のみ Public access を「有効」にし、コピー/セカンダリ作成後に「無効」に戻す
- クライアント IP をサーバーレベル・DB レベルのファイアウォールルールに限定する
- アプリケーションからの通常アクセスには引き続き Private Endpoint を使う
認証方式とロール設計
クロステナントのコピー/geo レプリケーションでは、Microsoft Entra ID 認証のみの構成はサポートされません。
- 少なくとも、移行用にSQL 認証ログイン(dbmanager 権限)を用意する
- アプリケーションの通常接続には Entra ID(Managed Identity など)を使い、移行時だけ SQL ログインを使う運用にする
- 移行完了後、SQL ログインの権限を落とす/削除することでリスクを低減
ユーザー/ログインの整合性
DB コピー/geo レプリケーションは、DB 内のユーザーと権限もコピーしますが、サーバーレベルログインとの対応が崩れることがあります。
- 可能であれば、アプリケーション接続には 含まれた(contained)データベースユーザーを使う
- サーバーレベルログインを使う場合は、ソース/ターゲットで同じ SID を持つログインをあらかじめ作成しておく
- geo レプリケーション構成時も、同様に SID を意識してログインを作る
監視と運用のポイント
大きな DB のコピーや geo レプリケーションでは、「どこまで進んでいるのか」「遅延がどのくらいあるか」を見える化しておくことが重要です。
sys.dm_database_copies(コピー進捗・状態)sys.dm_operation_status(コピー/geo レプリケーションなどの操作全体の状態)sys.dm_geo_replication_link_status(geo レプリケーションの遅延秒数など)
これらの DMV をダッシュボード化しておくと、「どのタイミングでカットオーバーしてよいか」の判断がしやすくなります。
まとめ
- 最適解はサービス側コピー:別テナントへの移行でも、ターゲット側サーバーから T‑SQL+SQL 認証で CREATE DATABASE … AS COPY OF を実行すれば正式にサポートされる。Hyperscale 同一リージョンなら Fast copy で非常に高速。
- ダウンタイム最小化にはアクティブ geo レプリケーション:別テナント間でも SQL 認証+T‑SQL で構成可能。計画フェールオーバーで停止時間を数分レベルに抑えられる。
- Private Endpoint には要注意:コピー/geo レプリケーション開始時は Public access を一時的に開ける必要がある。完了後に閉じる運用を前提に計画する。
- BACPAC は最終手段:どうしても必要なときは、同一リージョンの高性能 Azure VM で SqlPackage を実行し、DB 側も一時的にスケールアップするなどしてパフォーマンスを最大化する。
600GB クラスの Hyperscale DB でも、これらのポイントを押さえて設計すれば、「10時間以上かかる BACPAC」から卒業し、より短時間・低リスクで別テナントへの移行を実現できます。まずは検証環境でサービス側コピーと geo レプリケーションの両方を試し、自社の要件に合うカットオーバー方式を選定してみてください。

コメント