この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、菊池です。
MongoDBからのDMSレプリケーション、S3ターゲットに続きMySQLでも試してみました。これまでの記事は以下を参照ください。
- Database Migration Service の Source に MongoDB が選択可能になりました!
- [DMS] MongoDB Sourceのマイグレーションモードを比較する
- [DMS] MongoDB:テーブルモードのデータパターン検証
検証
SourceとしてEC2で動作するMongoDBのレプリカセット、TargetとしてRDS MySQLインスタンスを利用します。
- Source
- MongoDB 3.4.2
- レプリケーションモード:テーブルモード
- Target
- RDS for MySQL 5.6.27
初期データのマイグレーション
まずはデータを1つMongoDBに挿入し、レプリケーションを実行します。
s0-rs0:PRIMARY> use main
switched to db main
s0-rs0:PRIMARY>
s0-rs0:PRIMARY> db.users.insert(
... {
... userid : 001,
... name : "hoge1",
... joined : ISODate("2017-04-01"),
... likes : [ "tennis", "golf", "swimming" ]
... }
... );
WriteResult({ "nInserted" : 1 })
s0-rs0:PRIMARY>
s0-rs0:PRIMARY> db.users.find()
{ "_id" : ObjectId("5905346cb1ae627be955aca4"), "userid" : 1, "name" : "hoge1", "joined" : ISODate("2017-04-01T00:00:00Z"), "likes" : [ "tennis", "golf", "swimming" ] }
この状態でレプリケーションタスクを実行します。移行先のMySQLでデータベースを確認します。
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| awsdms_control |
| innodb |
| main |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
main
データベースが作成されています。テーブルも確認してみます。
mysql> show tables from main;
+----------------+
| Tables_in_main |
+----------------+
| users |
+----------------+
users
テーブルが作成されました。レコードを確認します。
mysql> select * from users;
+--------------------------+--------+-------+---------------------+----------------------------------+
| $OID:_id | userid | name | joined | $ARRAY:likes |
+--------------------------+--------+-------+---------------------+----------------------------------+
| 5905346cb1ae627be955aca4 | 1 | hoge1 | 2017-04-01 00:00:00 | [ "tennis", "golf", "swimming" ] |
+--------------------------+--------+-------+---------------------+----------------------------------+
1 row in set (0.00 sec)
レプリケーションが実行されました。配列の列は$ARRAY
で定義されています。
CDCの実行
続けてMongoDBにデータを追加して、CDCが実行されることを確認します。
s0-rs0:PRIMARY> db.users.insert(
... {
... userid : 002,
... name : "hoge2",
... joined : ISODate("2017-04-01"),
... }
... );
WriteResult({ "nInserted" : 1 })
s0-rs0:PRIMARY> db.users.find()
{ "_id" : ObjectId("5905346cb1ae627be955aca4"), "userid" : 1, "name" : "hoge1", "joined" : ISODate("2017-04-01T00:00:00Z"), "likes" : [ "tennis", "golf", "swimming" ] }
{ "_id" : ObjectId("59053611b1ae627be955aca5"), "userid" : 2, "name" : "hoge2", "joined" : ISODate("2017-04-01T00:00:00Z") }
s0-rs0:PRIMARY>
MySQLのデータを確認します。
mysql> select * from users;
+--------------------------+--------+-------+---------------------+----------------------------------+
| $OID:_id | userid | name | joined | $ARRAY:likes |
+--------------------------+--------+-------+---------------------+----------------------------------+
| 5905346cb1ae627be955aca4 | 1 | hoge1 | 2017-04-01 00:00:00 | [ "tennis", "golf", "swimming" ] |
| 59053611b1ae627be955aca5 | 2 | hoge2 | 2017-04-01 00:00:00 | NULL |
+--------------------------+--------+-------+---------------------+----------------------------------+
2 rows in set (0.00 sec)
データが同期されています。挿入したデータになかった項目はNULL
となっています。
次に、型が異なるデータを挿入してみます。joind
を文字列で挿入します。
s0-rs0:PRIMARY> db.users.insert(
... {
... userid : 003,
... name : "hoge3",
... joined : "2017-04-01",
... likes : [ "tennis" ]
... }
... );
WriteResult({ "nInserted" : 1 })
s0-rs0:PRIMARY> db.users.find()
{ "_id" : ObjectId("5905346cb1ae627be955aca4"), "userid" : 1, "name" : "hoge1", "joined" : ISODate("2017-04-01T00:00:00Z"), "likes" : [ "tennis", "golf", "swimming" ] }
{ "_id" : ObjectId("59053611b1ae627be955aca5"), "userid" : 2, "name" : "hoge2", "joined" : ISODate("2017-04-01T00:00:00Z") }
{ "_id" : ObjectId("59053671b1ae627be955aca6"), "userid" : 3, "name" : "hoge3", "joined" : "2017-04-01", "likes" : [ "tennis" ] }
s0-rs0:PRIMARY>
MySQL側では型が異なるとNULL
となっています。
mysql> select * from users;
+--------------------------+--------+-------+---------------------+----------------------------------+
| $OID:_id | userid | name | joined | $ARRAY:likes |
+--------------------------+--------+-------+---------------------+----------------------------------+
| 5905346cb1ae627be955aca4 | 1 | hoge1 | 2017-04-01 00:00:00 | [ "tennis", "golf", "swimming" ] |
| 59053611b1ae627be955aca5 | 2 | hoge2 | 2017-04-01 00:00:00 | NULL |
| 59053671b1ae627be955aca6 | 3 | hoge3 | NULL | [ "tennis" ] |
+--------------------------+--------+-------+---------------------+----------------------------------+
3 rows in set (0.00 sec)
先ほどのデータを更新して、正しいデータ型にupdateします。
s0-rs0:PRIMARY> db.users.updateOne(
... { userid : 003 },
... { $set: { joined : ISODate("2017-04-01") } }
... );
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
更新が反映されています。
mysql> select * from users;
+--------------------------+--------+-------+---------------------+----------------------------------+
| $OID:_id | userid | name | joined | $ARRAY:likes |
+--------------------------+--------+-------+---------------------+----------------------------------+
| 5905346cb1ae627be955aca4 | 1 | hoge1 | 2017-04-01 00:00:00 | [ "tennis", "golf", "swimming" ] |
| 59053611b1ae627be955aca5 | 2 | hoge2 | 2017-04-01 00:00:00 | NULL |
| 59053671b1ae627be955aca6 | 3 | hoge3 | 2017-04-01 00:00:00 | [ "tennis" ] |
+--------------------------+--------+-------+---------------------+----------------------------------+
3 rows in set (0.00 sec)
削除も試してみました。
s0-rs0:PRIMARY> db.users.deleteOne(
... { userid : 003 }
... );
{ "acknowledged" : true, "deletedCount" : 1 }
s0-rs0:PRIMARY> db.users.find()
{ "_id" : ObjectId("5905346cb1ae627be955aca4"), "userid" : 1, "name" : "hoge1", "joined" : ISODate("2017-04-01T00:00:00Z"), "likes" : [ "tennis", "golf", "swimming" ] }
{ "_id" : ObjectId("59053611b1ae627be955aca5"), "userid" : 2, "name" : "hoge2", "joined" : ISODate("2017-04-01T00:00:00Z") }
s0-rs0:PRIMARY>
削除もちゃんと同期されました。
mysql> select * from users;
+--------------------------+--------+-------+---------------------+----------------------------------+
| $OID:_id | userid | name | joined | $ARRAY:likes |
+--------------------------+--------+-------+---------------------+----------------------------------+
| 5905346cb1ae627be955aca4 | 1 | hoge1 | 2017-04-01 00:00:00 | [ "tennis", "golf", "swimming" ] |
| 59053611b1ae627be955aca5 | 2 | hoge2 | 2017-04-01 00:00:00 | NULL |
+--------------------------+--------+-------+---------------------+----------------------------------+
2 rows in set (0.00 sec)
まとめ
MongoDBからMySQLへのデータレプリケーションを試しました。
データモデルが異なるデータベースに対しても、一部制約はありつつも継続的なレプリケーションが可能です。移行だけでなく、フロント、非同期な集計、分析用途など、目的に応じて適切なデータベースを使っていくことも可能になります。