はじめに
こんにちは、インフラソリューション部の Kzzz です。普段は Terraform で AWS を扱い社内インフラの運用・保守・改善をしています。近年、コンプライアンスなどの対応のため、終了したサービスのデータベースを一定の期間保持しておかなければならないことが多くなってきました。
今回はそのような場合に、常に起動しておく必要はないが、たま〜に起動して使用できるようにデータベースをバックアップ・リストアする方法を AWS ドキュメントのAmazon Aurora MySQL DB クラスターへのデータの移行に記載されている3種類の方法を用いて試してみます!
試してみる移行方法
- Percona XtraBackup を使用したバックアップとリストア
- mysqldump を使用したバックアップとリストア
- テキストファイルを使用したバックアップとリストア
前提
目的
Amazon EC2 やオンプレなどの Amazon RDS 以外の環境で運用されていた 100 GB の MySQL データベースをアーカイブ化して保持したのち、Amazon Aurora MySQL にリストアして、ユーザーデータなどへアクセスできるようにします。検証環境のバージョン
今回の検証では、移行元データベースを手元の MacBook の Docker 内で作成したデータベースを使用します。オンプレ環境
PC : MacBook Pro 14inch, 2023, 16GBDocker : 24.0.6
MySQL : 8.0.28
Percona XtraBackup : 8.0.28-21
Docker Desktop の設定
Docker Desktop : v4.25.0CPU limit : 10
Memory limit : 8GB
Swap : 2GB
リストアに使用する EC2 インスタンス
AMI : Amazon Linux 2インスタンスタイプ : t2.small
MySQL : 8.0.28
Percona XtraBackup : 8.0.28-21
Amazon Aurora MySQL
エンジンバージョン : 8.0.mysql_aurora.3.04.1インスタンスクラス : db.t3.medium
準備
データベース移行検証に使うために mysql_random_data_load というランダムデータ生成ツールを使用して約 100 GB のデータベースを用意しました。
du -h /var/lib/mysql/
116K /var/lib/mysql/sys
804K /var/lib/mysql/#innodb_temp
36K /var/lib/mysql/mysql
1.6M /var/lib/mysql/performance_schema
100G /var/lib/mysql/test_db
101G /var/lib/mysql/
Percona XtraBackup を使用したバックアップとリストア
まず始めは、AWS ドキュメントの中で、mysqldump を使用した方法よりもかなり高速になる場合があると記載されている移行方法である Percona XtraBackup を使用した方法を試していきます。手順
Percona XtraBackup を使用した方法の手順は、このような流れで行っていきます。- Percona XtraBackup でバックアップの作成
- バックアップを Amazon S3 にアップロード
- Amazon RDS からバックアップをリストア
バックアップ
Percona XtraBackup のインストール
今回の移行環境が MySQL 8.0.28 なので Percona XtraBackup 8.0.28 をインストールします。自身の環境に合ったバージョンは Percona のダウンロードサイトで確認が必要です。
wget https://downloads.percona.com/downloads/Percona-XtraBackup-8.0/Percona-XtraBackup-8.0.28-21/binary/debian/buster/x86_64/percona-xtrabackup-80_8.0.28-21-1.buster_amd64.deb
dpkg -i percona-xtrabackup-80_8.0.28-21-1.buster_amd64.deb
xtrabackup --version
xtrabackup version 8.0.28-21 based on MySQL server 8.0.28 Linux (x86_64) (revision id: 78878e9b608)
バックアップファイルの作成
バックアップファイルは 公式ドキュメントに沿って 5 GB ずつに分割して作成していきます。今回は Amazon S3 へのアップロードに AWS CLI を使用するので、分割しなくても問題ありません。また Percona XtraBackup のバックアップファイルの圧縮形式は Gzip、tar、xbstream と複数ありますが MySQL 8.0 では xbstream のみしか対応していないので注意が必要です。
圧縮用に Percona xbstream のみをサポートします。Percona XtraBackup と Amazon S3 を使用した MySQL からの物理移行Percona XtraBackup で完全バックアップを作成します。
time xtrabackup --backup --user=<usename> --password=<password> --compress --compress-threads=4 --target-dir=/var/backups/xtrabackup --stream=xbstream | split -d --additional-suffix=.xbstream --bytes=5GB - /var/backups/xtrabackup/backup
real 17m6.070s
user 26m36.409s
sys 1m55.762s
ls /var/backups/xtrabackup
backup00.xbstream backup01.xbstream backup02.xbstream backup03.xbstream backup04.xbstream backup05.xbstream backup06.xbstream backup07.xbstream backup08.xbstream backup09.xbstream
du -h /var/backups/xtrabackup
46G /var/backups/xtrabackup
Amazon S3 バケットへバックアップファイルをアップロード
Amazon S3 のコンソールでバックアップファイルをアップロードするバケットを作成して、AWS CLI でアップロードします。 また、S3 バケットのストレージクラスは保持コストとデータ取り出し時間とのバランスのいい Glacier Instant Retrieval を指定していきます。
aws s3 cp /var/backups/xtrabackup/ s3://kzzz-mysql-backup-test/xtrabackup/ --recursive --storage-class GLACIER_IR
リストア
Amazon RDS で S3 のバックアップファイルからデータベースを復元
RDS > データベース > S3 から復元 で復元するデータベースの設定を行います。




条件を変えて復元してみる
先ほどは公式ドキュメントの手順通りにリストアしましたが、条件を色々と変更して復元時間が変わるか試してみました。| 条件 | バックアップ作成時間 | リストア時間 | バックアップファイルサイズ |
| 圧縮あり | 18 分 | 58 分 | 46 GB |
| 圧縮なし | 18 分 | 58 分 | 100 GB |
| 圧縮あり+5 GB で split | 17 分 | 56 分 | 46 GB |
| 圧縮なし+5 GB で split | 18 分 | 55 分 | 100 GB |
S3 にアップロードする際の時間と S3 のストレージ料金を少なくするため、基本的にバックアップファイルは圧縮した方が良さそうです。
結果
Percona XtraBackup を使用したバックアップとリストアにかかった時間の平均はこのようになりました。| バックアップ作成時間 | リストア時間 | トータル時間 |
| 18 分 | 58 分 | 76 分 |
mysqldump を使用したバックアップとリストア
次に mysqldump を使用した方法を試していきます。こちらの方法では、リストアを実行する環境を自分で用意しなきゃいけないので、手順がやや複雑になります。手順
mysqldump を使用した方法の手順は、このような流れで行っていきます。- mysqldump コマンドでバックアップを作成
- バックアップを Amazon S3 にアップロード
- リストア用 EC2 インスタンスを作成
- 移行先の Aurora MySQL インスタンスを作成
- mysqldump コマンドでリストア
バックアップ
バックアップファイルを作成
移行元のオンプレ環境で mysqldump コマンドを使用してバックアップファイルを作成します。バックアップファイルはアップロード時間の短縮とストレージ料金を削減するために pbzip2 で圧縮します。移行元のデータベースがある環境にログインして mysqldump コマンドを実行します。同時にパイプを利用してバックアップファイルを圧縮していきます。
time mysqldump -u root \
--databases test_db \
--single-transaction \
--order-by-primary \
--routines=0 \
--triggers=0 \
--events=0 \
-p | pbzip2 -p10 > /var/backups/mysqldump/backup.dump.bz2
real 92m44.723s
user 424m58.538s
sys 7m3.**957s**
Amazon S3 バケットへバックアップファイルをアップロード
AWS CLI でバックアップファイルを Amazon S3 にアップロードします。 S3 バケットのストレージクラスは保持コストとデータ取り出し時間とのバランスのいい Glacier Instant Retrieval を指定します。
aws s3 cp /var/backups/mysqldump/backup.dump.bz2 s3://kzzz-mysql-backup-test/mysqldump/ --storage-class GLACIER_IR
リストア
リストア用の EC2 インスタンスを作成
Amazon S3 にアップロードしたバックアップファイルをオンプレ環境にダウンロードして RDS へリストアする方法より AWS 内のネットワークで完結させた方がデータ転送料金を削減できるので、リストア用の EC2 インスタンスを作成してリストアをします。リストア用の EC2 インスタンスの構成は以下のようにしました。
| AMI | Amazon Linux 2 |
| インスタンスタイプ | t2.small |
移行先の Aurora MySQL インスタンスを作成
次に Amazon RDS で移行元の MySQL のバージョンと互換性がある Aurora MySQL インスタンスを作成します。 Amazon RDS の構成は以下のようにしました。| エンジンバージョン | 8.0.mysql_aurora.3.04.1 |
| インスタンスクラス | db.t3.medium |
mysqldump コマンドでリストア
Aurora MySQL インスタンスが立ち上がったら、リストア用の EC2 インスタンスの環境にログインし、mysqldump コマンドを使用してデータベースを移行します。 移行の際はパイプを使用してバックアップファイルのダウンロード、圧縮ファイルの解凍、mysqldump をまとめて実行します。
time aws s3 cp s3://kzzz-mysql-backup-test/mysqldump/backup.dump.bz2 - \
| pbzip2 -d \
| mysql -u <username> -h <RDSのエンドポイント> -p
real 344m36.031s
user 106m19.297s
sys 4m10.825s
結果
mysqldump コマンドを使用したバックアップとリストアにかかった時間はこのようになりました。オンプレから S3 へのバックアップファイルのアップロード時間はばらつきがあるため省略しています。| バックアップ作成時間 | リストア時間 | トータル時間 |
| 92 分 | 334 分 | 426 分 |
テキストファイル を使用したバックアップとリストア
最後にテキストファイルを使用した方法を試していきます。こちらの方法では、移行先の Aurora MySQL から直接 Amazon S3 のバックアップファイルをインポートするので、Aurora MySQL に適切な権限を設定する手順が必要になります。手順
- SELECT INTO OUTFILE コマンドでテキストファイルを作成
- テキストファイルを圧縮
- 圧縮したテキストファイルを Amazon S3 にアップロード
- 解凍用の EC2 インスタンスを作成
- 圧縮したテキストファイルを解凍
- 移行先の Aurora MySQL インスタンスを作成
- Aurora MySQL の権限設定
- Aurora MySQL からバックアップファイルをインポート
バックアップ
移行するテーブルのテキストファイルを作成
テキストファイルを使用する方法では、テーブル単位でテキストファイルを作成する必要があります。移行元のデータベースにログインし、SELECT INTO OUTFILE コマンドを実行して移行するテーブルのテキストファイルを作成します。
SELECT * FROM test_tb INTO OUTFILE '/var/backups/textfile/backup.txt' FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';
Query OK, 187320000 rows affected (1 hour 27 min 45.50 sec)
ls -lh backup.txt
-rw-r----- 1 mysql mysql 89G Dec 10 12:21 backup.txt
テキストファイルを pbzip2 で圧縮
他の方法と同様、バックアップファイルはアップロード時間の短縮とストレージ料金を削減するために pbzip2 で圧縮します。
time pbzip2 -p10 backup.txt
real 41m33.664s
user 411m36.183s
sys 2m11.885s
テキストファイルを S3 にアップロード
AWS CLI でバックアップファイルを Amazon S3 にアップロードします。S3 バケットのストレージクラスは保持コストとデータ取り出し時間とのバランスのいい Glacier Instant Retrieval を指定します。
time aws s3 cp /var/backups/textfile/backup.txt.bz2 s3://kzzz-mysql-backup-test/textfile/ --storage-class GLACIER_IR
リストア
解凍用の EC2 インスタンスを作成
テキストファイルを使用するリストア方法でも mysqldump を使用するリストア方法と同様に、Amazon S3 のデータ転送料金を削減するために解凍用の EC2 インスタンスを作成してバックアップファイルを解凍します。解凍用の EC2 インスタンスの構成も同様です。
| AMI | Amazon Linux 2 |
| インスタンスタイプ | t2.small |
Amazon S3 に保存されているバックアップファイルを解凍
mysqldump の方法と違いテキストファイルを使用する方法では、Aurora MySQL インスタンスから直接 Amazon S3 のバックアップファイルをリストアするので、事前に圧縮されているバックアップファイルを解凍する必要があります。解凍用の EC2 インスタンスにログインし、パイプを使用して Amazon S3 にあるバックアップファイルのダウンロード、解凍、Amazon S3 へのアップロードを一度に実行します。
time sudo aws s3 cp s3://kzzz-mysql-backup-test/textfile/backup.txt.bz2 - | pbzip2 -d | aws s3 cp - s3://kzzz-mysql-backup-test/textfile/backup.txt
real 90m35.299s
user 83m33.712s
sys 6m35.515s
Amazon RDS で移行先の Aurora MySQL インスタンスを作成
次に Amazon RDS で移行元の MySQL のバージョンと互換性がある Aurora MySQL インスタンスを作成します。Amazon RDS の構成は以下のようにしました。
| エンジンバージョン | 8.0.mysql_aurora.3.04.1 |
| インスタンスクラス | db.t3.medium |
移行に必要なアクセス権限を移行先クラスターに設定
Amazon S3 へアクセスできるように以下の IAM ポリシーを Aurora MySQL DB クラスターにアタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::kzzz-mysql-backup-test",
"arn:aws:s3:::kzzz-mysql-backup-test/*"
]
}
]
}
パラメータグループを作成
続いて、DB クラスターのパラメータグループを作成します。



VPC エンドポイントの作成
今回の環境は DB クラスターが Private サブネット内にあるので、このままでは S3 にアクセスできるよう DB クラスターのアウトバウンド接続を有効にする必要があります。VPC > エンドポイント > エンドポイントを作成 から S3 へのエンドポイントを作成します。
サービスでは Gateway タイプのものを、VPC では DB クラスターと同じものを選択してください。

Aurora MySQL インスタンスで AWS_LOAD_S3_ACCESS 権限を付与
Aurora MySQL インスタンスにログインしてデータをロードするための権限をユーザに付与するために GRANT コマンドを実行します。user と domain-or-ip-address は各自設定を変えてください。
GRANT AWS_LOAD_S3_ACCESS TO '`user`'@'`domain-or-ip-address`'
Aurora MySQL インスタンスに移行元のテーブルを作成
LOAD DATA FROM S3 コマンドではテーブル単位でデータをインポートするため、移行元と同じ構成のテーブルを移行先である DB クラスターに作成しておく必要があります。LOAD DATA FROM S3 コマンドで S3 のテキストファイルからテーブルをインポート
SELECT INTO OUTFILE コマンドでテキストファイルにしたときの形式に合わせてインポートします。
LOAD DATA FROM S3 's3://kzzz-mysql-backup-test/textfile/backup.txt'
INTO TABLE test_tb
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
Query OK, 187320000 rows affected (3 hours 27 min 54.45 sec)
Records: 187320000 Deleted: 0 Skipped: 0 Warnings: 0
結果
テキストファイルを使用したバックアップとリストアにかかった時間はこのようになりました。オンプレから S3 へのバックアップファイルのアップロード時間はばらつきがあるため省略しています。| バックアップ作成時間 | リストア時間 | トータル時間 |
| 87 分(テキストファイル作成時間) + 41 分(圧縮時間) | 90 分(解凍時間) + 207 分(インポート時間) | 425 分 |
バックアップファイルの有効期間とストレージコスト
バックアップファイルの有効期間
今回の移行先である Amazon Aurora MySQL v3 はバージョンの種類によって利用可能な期間は変わってきます。| バージョンの種類 | 利用可能期間 |
| Amazon Aurora マイナーバージョン | リリースから少なくとも 12 か月間 |
| Amazon Aurora マイナーバージョン(LTS) | リリースから少なくとも 3 年間 |
| Amazon Aurora メジャーバージョン | 少なくとも対応するコミュニティバージョンのコミュニティが終了するまで |
またマイナーバージョンに移行元 MySQL のバージョンを合わせるためにアップグレードする際は、MySQL 8.0 → MySQL 5.7 へのダウングレードはできないので注意が必要になります。
バックアップファイルのストレージコスト
Amazon S3 でバックアップファイルを保存しておく場合、別途ストレージコストがかかってきます。Amazon S3 でのバックアップファイル保持コスト(東京リージョン)
Amazon S3 のストレージクラスごとのストレージコスト、アクセス性能を比較すると以下のようになります。AWS のリージョンは東京リージョンです。| ストレージクラス | ストレージコスト/月 | データ取り出しコスト | アクセス性能の表記 |
| S3 標準 | 0.025USD/GB | 該当なし | 低レイテンシー |
| S3 標準 – 低頻度アクセス | 0.0138USD/GB | 0.01USD/GB | ミリ秒単位 |
| S3 One Zone – 低頻度アクセス | 0.011USD/GB | 0.01USD/GB | ミリ秒単位 |
| S3 Glacier Instant Retrieval | 0.005USD/GB | 0.03USD/GB | ミリ秒単位 |
| S3 Glacier Flexible Retrieval (標準) | 0.0045USD/GB | 0.011USD/GB | 1 分から 12 時間 |
| S3 Glacier Deep Archive (標準) | 0.002USD/GB | 0.022USD/GB | 12 時間以内 |
※ こちらは 2024 年 1 月のものになります。最新のコストは AWS ドキュメントの Amazon S3 の料金 ページを確認ください。
バックアップファイル (100 GB) の保持と初回取り出しにかかるコスト比較
100 GB のバックアップファイルを Amazon S3 に保存した期間と1回の取り出しにかかるコストの合計を 6 ヶ月分比較したグラフは以下のようになりました。
| 保持期間(100 GB) | 1 month | 6 month | 12 month | 24 month | 36 month |
| S3 標準 | 2.38 USD | 9.28 USD | 17.56 USD | 34.12 USD | 50.68 USD |
| S3 標準 – 低頻度アクセス | 2.50 USD | 15.00 USD | 30.00 USD | 60.00 USD | 90.00 USD |
| S3 One Zone – 低頻度アクセス | 2.10 USD | 7.60 USD | 14.20 USD | 27.40 USD | 40.60 USD |
| S3 Glacier Instant Retrieval | 3.50 USD | 6.00 USD | 9.00 USD | 15.00 USD | 21.00 USD |
| S3 Glacier Flexible Retrieval (標準) | 1.55 USD | 3.80 USD | 6.50 USD | 11.90 USD | 17.30 USD |
| S3 Glacier Deep Archive (標準) | 2.40 USD | 3.40 USD | 4.60 USD | 7.00 USD | 9.40 USD |
まとめ
今回色々な方法でバックアップ、リストアを行いこのような結果になりました。バックアップとリストアにかかったトータル時間
| 移行方法 | バックアップ作成時間 | リストア時間 | トータル時間 | 年間のストレージコスト+1回リストア |
| Percona XtraBackup を使用した方法 | 18 分 (46GB) | 57 分 | 75 分 + Amazon S3 へのアップロード時間 | 4.14 USD |
| mysqldump を使用した方法 | 92 分 (18.7 GB) | 344 分 | 436 分 + Amazon S3 へのアップロード時間 | 1.68 USD |
| テキストファイルを使用した方法 | 128 分 (18.6 GB) | 297 分 | 425 分 + Amazon S3 へのアップロード時間 | 1.67 USD |
感想
検証した結果、Percona XtraBackup が復元時間が短くコンソール上での作業などを鑑みても現状では 1 番良いと感じました。ですが Aurora MySQL では、Percona XtraBackup の機能が大幅に制限されており、compress オプションで使用できる圧縮形式も変更できれば更にバックアップファイルの容量を減らせるので対応されて欲しいと思います。
参考リンク
- https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Migrating.html
- https://docs.percona.com/percona-xtrabackup/8.0/index.html
- https://github.com/Percona-Lab/mysql_random_data_load
- https://www.percona.com/downloads
- https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html
- https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Migrating.ExtMySQL.S3.html
- https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/MySQL.Procedural.Importing.SmallExisting.html
- https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Integrating.LoadFromS3.html
- https://aws.amazon.com/jp/s3/pricing/