AWS DMSを使ってPostgreSQLからMySQLへ移行した

趣味で作っているRailsアプリは、PostgreSQLで動いていたのですが最近は業務でMySQLを使う事が多いのでMySQLに寄せていこう、と思い(AWSにに慣れるためにも)RDS MySQLへ移行することにしました。

移行には、fixture経由でのエクスポート/インポートでもいけますが、使ったことがなかったのでDMSを使ってみました。
https://ap-northeast-1.console.aws.amazon.com/dms/home

DMSはレプリケーションを使ってデータの同期をするのでソースとなるDBでレプリケーションできるようにする必要があります。
ドキュメントにあるように、いくつか設定ファイルの変更が必要です。
http://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_Source.PostgreSQL.html

他には、AWSからレプリケーションできるように、 /etc/postgresql/9.4/main/postgresql.conf の listen_addresseshost replication rep 0.0.0./0 md5 が必要です。

また、タスク作成時には、ターゲットとなるMySQLのデータベースに指定したDB名で格納するには、以下ルールを設定しました。

  • Selection rules
    • where schema name is like 'public' and table name is like '%', include
  • Transformation rules
    • For schema where schema name is like 'public', rename to 'antena_production'

想定外だったのですがデータの移行には完了すると、スキームが微妙に変更されてました。

  • index が消える
  • autoincliment が消える
    • ドキュメントに書いている
  • boolean => varchar(5) になる
  • 文字コードがutf8mb4にならない
    • ドキュメントに書いている
  • datetime 型などに limit がついている
    • 問題ないけどdb/schema.rbに差分がでる

本来のスキームに合わせるために、RDS MySQLからのダンプをローカル環境にリストアして、rake db:migrate を実行し、db/schema.rb との差分を確認します。差分を見て正しい状態になるようalterクエリ実行していきます。
下記はalterクエリの断片です。

ALTER TABLE opinions CONVERT TO CHARACTER SET utf8mb4;
ALTER TABLE categories CONVERT TO CHARACTER SET utf8mb4;
ALTER TABLE posts CONVERT TO CHARACTER SET utf8mb4;
[...]

%w[
  posts
  opinions
  sites
  categories
  posts
].each do |table_name|
  ActiveRecord::Base.connection.execute <<-SQL
    ALTER TABLE #{table_name} MODIFY `id` int NOT NULL AUTO_INCREMENT;
  SQL
end

ActiveRecord::Migration::change_column :categories, :name, :string, limit: 191
ActiveRecord::Migration::change_column :categories, :slug, :string, limit: 191
ActiveRecord::Migration::change_column :categories, :identity, :string, limit: 191
ActiveRecord::Migration::change_column :categories, :created_at, :datetime, limit: nil
ActiveRecord::Migration::change_column :categories, :updated_at , :datetime, limit: nil

移行できました。