![[新機能]Amazon Auroraで高速にクローンを作成できます](https://devio2023-media.developers.io/wp-content/uploads/2014/05/Amazon_RDS.png)
[新機能]Amazon Auroraで高速にクローンを作成できます
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
大栗です。
Amazon Auroraでデータベースのクローンを作成できる機能がリリースされました!
データベース・クローン
データベースのクローンはre:Invent 2016でアナウンスされていたのですが、既存のAuroraクラスタを素早くコスト効率よく複製する機能です。データベースのクローンではCopy-on-Writeプロトコルを使用しており、ソースデータベースかクローンデータベースで書き換えが発生した時にデータがコピーされます。
Copy-on-Writeプロトコル
Copy-on-WriteはOSのメモリ管理などでよく使用されますが、データの複製を行う時に実際にはコピーせずに同じデータを共有して複製時から変更がある時にオリジナルのデータをコピーします。Wikipediaによると『原本またはコピーのどちらかを書き換えようとしたときに、それを検出し、その時点ではじめて新たな空き領域を探して割り当て、コピーを実行する』と述べています。
つまりソースデータベースかクローンデータベースに何らかの変更が発生した時にストレージ側で実際にコピーを行うということです。
制限事項
データベースのクローンでは、以下の制限があります。
- リージョン間でクローンデータベースを作成することはできません。クローンデータベースは、ソースデータベースと同じリージョンに作成する必要があります。
- 同じソースデータベースの他のクローンから作成されたクローンを含めて、最大15個のクローンを現在持つことができます。それ以降のクローンはソースデータベースの完全コピーになります。
- クロスアカウントのデータベースクローンは現在サポートされていません。
- 異なるVPCにクローンを提供できますが、VPCのサブネットが同じAZにマッピングされている場合に限ります。
試してみた
事前準備
事前にAuroraクラスタを作成して、データを JdbcRunnerのTiny TPC-Cを使用してTPC-C用のデータをwarehouseを10としてデータ投入しています。約1GBのデータが保存されます。
java JR scripts/tpcc_load.js -nAgents 8 -param0 10
約1GBのデータが保存されます。
mysql> select table_schema, sum(data_length+index_length) /1024 /1024 as MB from information_schema.tables group by table_schema order by sum(data_length+index_length) desc; +--------------------+---------------+ | table_schema | MB | +--------------------+---------------+ | tpcc | 1048.70312500 | | mysql | 7.24774456 | | information_schema | 0.01074219 | | performance_schema | 0.00000000 | +--------------------+---------------+ 4 rows in set (0.14 sec)
CloudWatch上でも約1GBのデータが確認できます。

Management Consoleでクローンを行う
クローン元のDBインスタンスを選択して、[インスタンスの操作]-[クローンの作成]をクリックします。

以下の用に「インスタンスの仕様」、「設定」、「ネットワーク & セキュリティ」、「データベースの設定」、「メンテナンス」を指定してクローンの作成をクリックします。VPCを選択できるので別のVPCにクローンを作成することもできます。

クラスタが作成されます。

DBインスタンスも作成されます。

Auroraにログインしてみます。
$ mysql -u awsuser -p -h clone01-cluster.cluster-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 113 Server version: 5.6.10 MySQL Community Server (GPL) Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>
約1GBのデータが保存されています。
mysql> select table_schema, sum(data_length+index_length) /1024 /1024 as MB from information_schema.tables group by table_schema order by sum(data_length+index_length) desc; +--------------------+---------------+ | table_schema | MB | +--------------------+---------------+ | tpcc | 1048.70312500 | | mysql | 7.24774456 | | information_schema | 0.01074219 | | performance_schema | 0.00000000 | +--------------------+---------------+ 4 rows in set (0.14 sec)
しかし、CloudWatchでAuroraクラスタのVolumeBytesUsedを確認すると100MB程度になっています。クローン作成中のデータに600MB程度のポイントがありますが、一時的なものになっています。

AWS CLIでクローンを行う
今度はCLIでクローンを作成します。restore-db-cluster-to-point-in-timeコマンドを使用するのですが、--restore-typeでcopy-on-writeを指定することでデータベースクローンができます。
$ aws rds restore-db-cluster-to-point-in-time \
>     --db-cluster-identifier clone03 \
>     --restore-type copy-on-write \
>     --source-db-cluster-identifier source-cluster \
>     --use-latest-restorable-time \
>     --db-subnet-group-name default \
>     --vpc-security-group-ids sg-xxxxxxxx
{
    "DBCluster": {
        "MasterUsername": "awsuser",
        "ReaderEndpoint": "clone03.cluster-ro-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com",
        "ReadReplicaIdentifiers": [],
        "CloneGroupId": "12345678-1234-1234-1234-123456789012",
        "VpcSecurityGroups": [
            {
                "Status": "active",
                "VpcSecurityGroupId": "sg-xxxxxxxx"
            }
        ],
        "HostedZoneId": "12345678901234",
        "Status": "creating",
        "MultiAZ": false,
        "PreferredBackupWindow": "20:00-20:30",
        "DBSubnetGroup": "default",
        "AllocatedStorage": 1,
        "BackupRetentionPeriod": 1,
        "PreferredMaintenanceWindow": "fri:18:13-fri:18:43",
        "Engine": "aurora",
        "Endpoint": "clone03.cluster-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com",
        "AssociatedRoles": [],
        "IAMDatabaseAuthenticationEnabled": false,
        "ClusterCreateTime": "2017-06-13T02:24:09.236Z",
        "EngineVersion": "5.6.10a",
        "DBClusterIdentifier": "clone03",
        "DbClusterResourceId": "cluster-ABCDEFGHIJKLMNOPQRSTUVWXYZ",
        "DBClusterMembers": [],
        "DBClusterArn": "arn:aws:rds:ap-northeast-1:123456789012:cluster:clone03",
        "StorageEncrypted": false,
        "DatabaseName": "mydb",
        "DBClusterParameterGroup": "aurora-test-001",
        "AvailabilityZones": [
            "ap-northeast-1a",
            "ap-northeast-1c"
        ],
        "Port": 3306
    }
}Auroraクラスタが作成されます。DBインスタンスは作成されないので、別途作成する必要があります。
クローンの動きを確認する
データに変更があった時に実際のコピーを行うので、その時のデータ量の変化について確認してみます。
データ挿入した時の挙動
各テーブルに1行ずつデータを挿入しました。すると79,413,248バイトから79,446,016バイトと32KBのデータ量が増加しました。

別のクラスタで以下のような小さいテーブルに対して1件挿入した場合に増えるデータサイズを確認してみます。
mysql> desc new_orders ; +---------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+---------+------+-----+---------+-------+ | no_o_id | int(11) | NO | PRI | 0 | | | no_d_id | int(11) | NO | PRI | 0 | | | no_w_id | int(11) | NO | PRI | 0 | | +---------+---------+------+-----+---------+-------+ 3 rows in set (0.00 sec)
79,413,248バイトから79,429,632バイトと16KBのデータ量が増加しました。ここで増える16KBがCopy-on-Writeを行う単位のページのサイズと考えられると思われます。

テーブルをTRUNCATEした時の挙動
全テーブルをTRUNCATEします。外部キー制約のチェックを無視するためforeign_key_checksを0にして実行しました。
mysql> set foreign_key_checks = 0; Query OK, 0 rows affected (0.00 sec) mysql> truncate table customer ; Query OK, 0 rows affected (0.03 sec) mysql> truncate table district ; Query OK, 0 rows affected (0.03 sec) mysql> truncate table history ; Query OK, 0 rows affected (0.02 sec) mysql> truncate table item ; Query OK, 0 rows affected (0.03 sec) mysql> truncate table new_orders; Query OK, 0 rows affected (0.02 sec) mysql> truncate table order_line; Query OK, 0 rows affected (0.03 sec) mysql> truncate table orders ; Query OK, 0 rows affected (0.02 sec) mysql> truncate table stock ; Query OK, 0 rows affected (0.02 sec) mysql> truncate table warehouse ; Query OK, 0 rows affected (0.02 sec) mysql> mysql> set foreign_key_checks = 1; Query OK, 0 rows affected (0.00 sec) mysql>
データサイズをCloudWatchで確認すると以下のようになり、サイズに変更がありません。TRUNCATEでは内部でテーブルの再作成をしているため既存のデータに変更が無く、データ量に変化がないと考えられます。

レコードをDELETEした時の挙動
今度はTRUNCATEではなく全件DELETEをしてみます。
mysql> set foreign_key_checks = 0; Query OK, 0 rows affected (0.02 sec) mysql> delete from customer ; Query OK, 300000 rows affected (23.90 sec) mysql> delete from district ; Query OK, 100 rows affected (0.02 sec) mysql> delete from history ; Query OK, 300000 rows affected (12.00 sec) mysql> delete from item ; Query OK, 100000 rows affected (3.59 sec) mysql> delete from new_orders; Query OK, 90000 rows affected (3.32 sec) mysql> delete from order_line; Query OK, 2997884 rows affected (1 min 56.95 sec) mysql> delete from orders ; Query OK, 300000 rows affected (12.10 sec) mysql> delete from stock ; Query OK, 1000000 rows affected (57.22 sec) mysql> delete from warehouse ; Query OK, 10 rows affected (0.02 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec)
今度はCloudWatch上のデータサイズが増加しました。レコードを削除しているのですが、データの変更により実際にコピーされたためデータサイズが増えたと考えられます。

クローンを多数作成した時の挙動
制限事項に『同じソースデータベースの他のクローンから作成されたクローンを含めて、最大15個のクローンを現在持つことができます。それ以降のクローンはソースデータベースの完全コピーになります』という物があるため、実際に完全コピーとなるか確認してみます。
CLIでクローンを作成して、クローンを合計で16個作成してみました。しかし、データ量は70MBと少しとなっており完全コピーがされずに済んでいます。

そこで17個目のクローンを作成してみました。すると今度は1GB程度のデータサイズとなり完全コピーされていると分かります。

16個目で完全コピーされなかったのは一時的に制限が緩和されているだけだと思われますので、本来は完全コピーされるものと思われます。同じデータを多数のクラスタやインスタンスで参照するとパフォーマンスの劣化を招くと考えられますので大量のクローンは作成しないほうが良いと思われます。
ソースデータベースを変更した時の挙動
今まではクローンデータベース側を変更していましたが、ソースデータベースを変更した時の挙動を確認してみます。データサイズの変化が大きかった全件DELETEをソースデータベースに対して実行してみます。
mysql> set foreign_key_checks = 0; Query OK, 0 rows affected (0.02 sec) mysql> delete from customer ; Query OK, 300000 rows affected (23.90 sec) mysql> delete from district ; Query OK, 100 rows affected (0.02 sec) mysql> delete from history ; Query OK, 300000 rows affected (12.00 sec) mysql> delete from item ; Query OK, 100000 rows affected (3.59 sec) mysql> delete from new_orders; Query OK, 90000 rows affected (3.32 sec) mysql> delete from order_line; Query OK, 2997884 rows affected (1 min 56.95 sec) mysql> delete from orders ; Query OK, 300000 rows affected (12.10 sec) mysql> delete from stock ; Query OK, 1000000 rows affected (57.22 sec) mysql> delete from warehouse ; Query OK, 10 rows affected (0.02 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec)
この時のデータサイズの変化をCloudWatchで確認するとソースデータベースのサイズだけ増えています。Log Structured Storageのお陰でソースデータベースの既存データが残った状態で、変更分を追記しているためクローンデータベースのサイズに変化がないと思われます。

まとめ
データベースクローンは素早く作成できて、コスト効率も良くデータベースを複製できます。これにより大量のデータを保存している本番DBと同じデータを使用した検証が簡単にできるようになりました。この機能によりDBへの変更を伴うアプリケーションのデプロイなどでも活用できると思われます。新しいアプリケーションをデプロイする時にクローンに対してDB変更を実施すれば、不具合があった場合の切り戻しも容易になります。
しかし、多量のデータ更新を行うと実際にデータコピーされることで、使用データサイズがスナップショットからリストアを行った場合と同程度になることもあります。データの追加だけでなく、データ削除の場合もコピーがされるので注意が必要です。










