SQL Serverのネイティブバックアップ機能でRDS for SQL Serverにリストアしてみる
はじめに
こんにちは、ぐっさんです。
SQL ServerをAWS RDS for SQL Serverに移行する検証として、ネイティブバックアップ/リストア機能を試してみました。
RDS for SQL Serverのオプショングループに SQLSERVER_BACKUP_RESTORE というオプションがあり、これを有効にするとSQL Serverの .bak ファイルをS3経由でRDSにリストアできます。
構成
今回の検証では、オンプレミス環境を模擬したEC2(Windows Server + SQL Server 2019)を移行元として使用します。移行先のRDSはSQL Server 2022を選択しました。リアルな移行要件を想定した構成での検証です。
検証のため、サブネットは分けていません。

制限事項
公式ドキュメントに記載されている主な制限事項を事前に確認しておきましょう。
| 項目 | 制限 |
|---|---|
| S3バケットのリージョン | RDSと同一リージョンのみ(クロスリージョン不可) |
| 同時実行タスク数 | 最大2タスクまで |
| 1ファイルのサイズ上限 | 5TB |
| DBサイズ上限 | 64TiB(Express Editionは10GB) |
| タイムゾーン | 異なるタイムゾーン間のリストアは非推奨 |
前提条件
今回の手順は、以下が作成済みであることを前提として進めます。
EC2にはFleet Managerを使用してログインします。
| リソース | 状態 |
|---|---|
EC2① SQL Server用(2019のAMI使用Windows_Server-2019-English-Full-SQL_2019_Standard-2026.04.15) |
作成済み(移行元DB稼働中・SQL Server認証用ユーザー作成済み) |
EC2② RDSに接続するSSMS用(2025のAMI使用Windows_Server-2025-English-Full-Base-2026.04.15) |
作成済み(SSMS インストール済み) |
| RDS for SQL Server(2022) | 作成済み(オプショングループは後述の手順で設定) |
| AWS CLI(EC2①) | インストール済み |
| SSM VPCエンドポイント(Fleet Manager用) | 作成済み(ssm / ssmmessages) |
| S3 Gateway VPCエンドポイント | 作成済み |
バックアップ保管用のS3バケットは、手順の中で新規作成します。
補足: SSMS、CLIのインストールについて
今回の検証環境はプライベートサブネットに配置しているためインターネットに接続できません。SSMSやAWS CLIはインストール時のみNAT Gatewayを一時的に作成してインターネット接続を確保しました。インストール完了後にNAT Gatewayを削除しています。
Step 1: S3バケットの作成
AWSマネジメントコンソールからS3バケットを作成します。
- S3コンソールを開き、「バケットを作成」 をクリック

- 以下を設定する
| 項目 | 値 |
|---|---|
| バケット名 | 任意(例: my-rds-backup-bucket) |
| AWSリージョン | RDSと同じリージョン(例: アジアパシフィック(東京)) |
| その他 | デフォルトのまま |

- 「バケットを作成」 をクリック

ポイント: S3バケットのリージョンはRDSと必ず同一にしてください。クロスリージョンはサポートされていません。
Step 2: IAMロールの作成(RDS用)
RDSがS3にアクセスするためのIAMロールを作成します。先にポリシーを作成してからロールを作成します。
2-1. 許可ポリシーの作成
- IAMコンソール → 「ポリシー」 → 「ポリシーを作成」 をクリック
- 「JSON」 タブを選択し、以下を入力する
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::<バケット名>"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObjectAttributes",
"s3:GetObject",
"s3:PutObject",
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload"
],
"Resource": "arn:aws:s3:::<バケット名>/*"
}
]
}

- ポリシー名(例:
poc-rds-s3-access-policy)を入力して 「ポリシーを作成」

ポイント:
s3:GetBucketLocationを忘れると、リストア実行時に権限エラーが発生します。
2-2. ロールの作成
- IAMコンソール → 「ロール」 → 「ロールを作成」 をクリック
- 「カスタム信頼ポリシー」 を選択し、以下のポリシーを入力し 「次へ」 をクリック
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "rds.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}

- 2-1で作成したポリシー(
poc-rds-s3-access-policy)を検索してチェック → 「次へ」

- ロール名(例:
poc-rds-s3-access-role)を入力して 「ロールを作成」

Step 3: オプショングループの作成
SQLSERVER_BACKUP_RESTORE オプションを有効にしたオプショングループを作成します。
3-1. オプショングループの作成
- RDSコンソール → 左メニュー 「オプショングループ」 → 「グループの作成」 をクリック

- 以下を設定し 「作成」 をクリック
| 項目 | 値 |
|---|---|
| 名前 | 任意(例: poc-sqlserver-options) |
| 説明 | 任意の文字列(入力必須) |
| エンジン | RDSのエンジンエディションと合わせる(例: sqlserver-se) |
| メジャーエンジンバージョン | RDSのバージョンと合わせる(例: 16.00) |

3-2. オプションの追加
- 作成したオプショングループを選択 → 「オプションの追加」 をクリック

- 「オプション名」 で
SQLSERVER_BACKUP_RESTOREを選択 - 「IAM ロール」 に Step 2 で作成したロールを入力する
- スケジューリングを 「今すぐ」 に設定して 「オプションの追加」 をクリック

オプショングループの詳細で、 SQLSERVER_BACKUP_RESTORE が追加されていることを確認

Step 4: RDSへのオプショングループの適用
- RDSコンソール → 「データベース」 → 対象のRDSインスタンスを選択
- 「変更」 をクリック

- 「追加設定」 セクションの 「オプショングループ」 で、Step 3 で作成したオプショングループを選択

- ページ下部の 「続行」 → 次のページで 「すぐに適用」 を選択して 「DBインスタンスを変更」 をクリック


適用後、RDSインスタンスのステータスが 「変更中」 になります。「利用可能」 に戻るまで待ってから次のステップに進んでください。
Step 5: テストDBの作成とデータ投入(EC2①)
移行対象のデータベースを作成し、簡単なテストデータを投入します。SSMSのクエリウィンドウで実行します。
- 対象のSQL ServerにSSMSから接続

- 新しいクエリを実行

- 以下のクエリでテストデータ投入
-- DBの作成
CREATE DATABASE [TestDB]
COLLATE Japanese_CI_AS;
GO
USE [TestDB];
GO
-- テーブルの作成
CREATE TABLE [dbo].[SampleData] (
Id INT IDENTITY(1,1) PRIMARY KEY,
Col1 NVARCHAR(100),
Col2 NVARCHAR(100),
Col3 NVARCHAR(200),
CreatedAt DATETIME DEFAULT GETDATE()
);
GO
-- 約1GBになるまでデータを投入
DECLARE @i INT = 0;
WHILE @i < 1500
BEGIN
INSERT INTO [dbo].[SampleData] (Col1, Col2, Col3)
SELECT TOP 1000
REPLICATE(N'あ', 50),
REPLICATE(N'い', 50),
REPLICATE(N'う', 100)
FROM sys.all_objects;
SET @i = @i + 1;
END
GO

エラーがないこと

- データベースができていることを確認
「Databases」を右クリック → 「Refresh」を実行

新しいデータベースが存在していること

- 以下のクエリでサイズを確認
-- DBサイズの確認
SELECT
DB_NAME() AS DatabaseName,
SUM(size * 8 / 1024) AS SizeMB
FROM sys.database_files;

およそ1GB分データが投入できている

Step 6: バックアップファイルの作成(EC2①)
移行元のSQL ServerでバックアップをEC2①から取得します。
6-1. バックアップ用フォルダの作成
Fleet ManagerでEC2①に接続し、PowerShellで作成します。
New-Item -ItemType Directory -Path C:\backup
空のフォルダができること

6-2. バックアップの実行
SSMSのクエリウィンドウで実行します。
BACKUP DATABASE [TestDB]
TO DISK = 'C:\backup\TestDB.bak'
WITH COMPRESSION, STATS = 10;

エラーがないこと

バックアップフォルダに .bak ファイルが存在すること

Step 7: S3へのアップロード(EC2①)
EC2①でAWS CLIを使ってバックアップファイルをS3にアップロードします。
(EC2にS3アクセスが可能なIAMロールの付与が必要です。)
aws s3 cp C:\backup\TestDB.bak s3://<バケット名>/TestDB.bak --region ap-northeast-1
# アップロード確認
aws s3 ls s3://<バケット名>/
結果

S3のコンソールでもファイルがあることが確認できます。

Step 8: RDSへのリストア実行(EC2②)
EC2②のSSMSでRDSのエンドポイントに接続します。

以下のストアドプロシージャを実行します。
exec msdb.dbo.rds_restore_database
@restore_db_name = 'TestDB',
@s3_arn_to_restore_from = 'arn:aws:s3:::<バケット名>/TestDB.bak';
クエリ画面

結果は即座に返りますが、バックグラウンドでリストアが進行しています。

Step 9: リストア状況の確認
以下のストアドプロシージャを実行します。
exec msdb.dbo.rds_task_status @db_name = 'TestDB';

lifecycle 列の値で進捗を確認します。
主なステータス情報
| lifecycle | 意味 |
|---|---|
| CREATED | タスク作成済み(開始待ち) |
| IN_PROGRESS | リストア中 |
| SUCCESS | 完了 |
| ERROR | エラー(task_info 列でエラー詳細を確認) |
rds_task_status について詳細は以下に記載があります。
SUCCESS になったらSSMSのObject Explorerで対象DBが表示されます。
最新情報にリフレッシュすると対象のDBが存在している


補足: 複数タスクが表示される場合
同じDB名で過去にリストアを実行したことがある場合、履歴タスクも表示されます。この場合、created_atが最新のものを確認します。また、過去の実行履歴がある場合はtask_idが1から始まらないことがあります。
Step 10: データ確認
以下のクエリでデータベースの中身を確認
USE [TestDB];
GO
-- テーブル一覧の確認
SELECT name FROM sys.tables;
-- データ件数の確認
SELECT COUNT(*) FROM [dbo].[SampleData];
-- 先頭データの確認
SELECT TOP 10 * FROM [dbo].[SampleData];

DBサイズも確認し、移行元と一致していることを確認します。
USE [TestDB];
GO
-- DBサイズの確認(移行元と照合)
SELECT
DB_NAME() AS DatabaseName,
SUM(size * 8 / 1024) AS SizeMB
FROM sys.database_files;

出会ったエラー
rds_task_status が ERROR になった
RDSへのリストア実行中のことです。
IAMポリシーに s3:GetBucketLocation を含めていなかったため以下のようなエラーが発生しました。
User: arn:aws:sts::...:assumed-role/poc-rds-s3-access-role/... is not authorized to perform:
s3:GetBucketLocation on resource: "arn:aws:s3:::<バケット名>"
→ Step 2 のポリシーに s3:GetBucketLocation を含めることで解消しました。
S3バケットのリージョン確認に必要なようですね。
まとめ
RDS for SQL Serverのネイティブバックアップ/リストア機能を使うと、 .bak ファイルをもとにS3経由でRDSに移行できます。
オプショングループを意識して使うことがあまりないので、確認する良い機会となりました。
今回は先にRDSが存在する前提で設定していますが、オプショングループはRDS作成時に設定も可能です。リストアを予定している場合は最初から設定しておいた方がスムーズです。
ポイント
SQLSERVER_BACKUP_RESTOREオプショングループの設定が必要- IAMロールに
s3:GetBucketLocationを含むS3権限が必要 - リストアはDB単位で実施(複数DBがある場合は繰り返し)
- 大容量DBの場合はS3アップロード時間・リストア時間を考慮したダウンタイム計画が必要
この記事が移行対応を予定している方の参考になれば幸いです。お読みいただきありがとうございました!








