mongify を使って、MySQL から MongoDB にデータを移行したので、その手順をまとめておく。
注意!
mongifyは多段(複層)embed(country < state < city
のような関係)には対応していない!
※mongify1.3.0にて非対応を確認済み
※あくまでもmongifyが対応していないというだけで、mongodb や mongoid は対応している。
mongify のインストール
mongifyが正常に動作する環境を作るのに苦労した。バージョンの制約が激しいので、bundlerで使用するgemを指定するのをオススメ。
※OSはWindows8.1。
動作したバージョンの組み合わせ
gem | Ruby2.0, 2.1, 2.3で確認 |
---|---|
mongify | 1.3.0 ※1.2.4ではNG |
activesupport | 4.2.7.1 |
activerecord | 4.2.7.1 |
activerecord-mysql2-adapter | 0.0.3 |
mysql2 | 0.4.4 |
bson | 1.10.2 もしくは 1.12.5 |
bson_ext | 1.10.2 もしくは 1.12.5 |
mongo | 1.10.2 もしくは 1.12.5 |
参考までにGemfileを。環境によってはもっと色々記述する必要がある。
# frozen_string_literal: true
source "https://rubygems.org"
gem "activesupport", '~>4.2'
gem "activerecord", '~>4.2'
gem 'mongify', '1.3.0'
gem 'mongo', '~>1.10'
gem 'mysql2'
gem 'activerecord-mysql2-adapter'
また、activerecord-mysql2-adapter のinstallで、以下の指示が表示された。
> gem install activerecord-mysql2-adapter
Fetching: mysql2-0.4.4-x86-mingw32.gem (100%)
======================================================================================================
You've installed the binary version of mysql2.
It was built using MySQL Connector/C version 6.1.6.
It's recommended to use the exact same version to avoid potential issues.
At the time of building this gem, the necessary DLL files were retrieved from:
http://cdn.mysql.com/Downloads/Connector-C/mysql-connector-c-6.1.6-win32.zip
This gem *includes* vendor/libmysql.dll with redistribution notice in vendor/README.
======================================================================================================
分かったような分からないような記述でちょっと困ったが、記載されているzipファイルをダウンロードし、こちらを参考にして、ruby.exeが格納されているディレクトリに libmysql.dll をコピーした。
接続設定ファイルの作成
sql_connection do
adapter "mysql2" ← ★"mysql"も試したが、最終的にはこれでいけた.
host "localhost"
username "root"
password "xxx"
database "xxx"
end
mongodb_connection do
host "localhost"
database "xxx"
# mLab MongoDB 用にはこれらの設定も必要
# host "dxxxxxx.mlab.com"
# database "xxx"
# port "37814"
# username "ユーザー名"
# password "パスワード"
end
接続確認 mongify check
の実行
bundler を使う場合は、コマンドの前に bundle exec を付ける。(以降同じ)
> mongify check f:\db\tmp\database.config
DL is deprecated, please use Fiddle
SQL connection works
NoSQL connection works
※参考: NGログ
> mongify check f:\db\tmp\database.config
C:/RailsInstaller/Ruby2.2.0/lib/ruby/site_ruby/2.2.0/rubygems/dependency.rb:310:in `to_specs': Please install the mysql2
adapter: `gem install activerecord-mysql2-adapter` (Could not find 'mysql2' (~> 0.3.10) - did find: [mysql2-0.4.2-x86-m
ingw32] (LoadError)
Checked in 'GEM_PATH=xxx)
既存データベースからテーブル情報を取得 mongify translation
の実行
> mongify translation f:\db\tmp\database.config > f:\db\tmp\translation.rb
transration.rb の中身をしっかり編集
referrenceにするのかembedするのか ※多段(複層)のembedにはmongifyが対応していないので注意。
不要カラムを移行対象から外す ※idカラム(恐らく:keyが付いているカラム)は自動的に削除される
不要テーブル(schema_migrationsなど)を移行対象から外す
データ移行 mongify process
の実行
MySQLのdumpファイルサイズがzip圧縮で1MBちょっとしかなくても、移行には20分近くかかった。(embed と referrence処理に時間がかかる。)
> mongify process f:\db\tmp\database.config f:\db\tmp\translation.rb
DL is deprecated, please use Fiddle
Copying xxxs (1/1): (163/163) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:00
:
Updating References xxxs: (163/163) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:00
:
Embedding yyyys (1/3): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:01:50
:
Removing pre_mongified_id xxxs: (1/1) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:00
参考: mongify 1.2.4 で発生したエラー。ActiveRecordのバージョンが合っていない、もしくは mongify が古いのが原因だと思われる。
> mongify process f:\db\tmp\database.config f:\db\tmp\translation.rb
DL is deprecated, please use Fiddle
C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/mongify-1.2.4/lib/mongify/database/column.rb:246:in `type_cast': un
defined method `string_to_time' for ActiveRecord::ConnectionAdapters::Column:Class (NoMethodError)
参考: 大量データを処理していると、最後の最後にエラーが発生することも(-_-)
どうやら Cursor がタイムアウト(MongoDBのデフォルトでは10分らしい)に引っかかってしまったようだ。
Updating References xxxs: (21815/21815) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:07:16
C:/Ruby/Ruby23/lib/ruby/gems/2.3.0/gems/mongo-1.10.2/lib/mongo/networking.rb:221:in `check_response_flags': Query respon
se returned CURSOR_NOT_FOUND. Either an invalid cursor was specified, or the cursor may have timed out on the server. (M
ongo::OperationFailure)
from C:/Ruby/Ruby23/lib/ruby/gems/2.3.0/gems/mongo-1.10.2/lib/mongo/networking.rb:214:in `receive_response_heade
r'
timeout回避のために、サービス起動引数に以下を追加してみたが効果なし。
--setParameter cursorTimeoutMillis=1200000
仕方ないので mongify 1.3.0 のソースコードを自前で修正した。
https://github.com/leon-joel/mongify
※目的地には限りなく遠回りしているような気もするが…
mongify.gemspecを適当に修正して、gem build
する。
そして、gemをインストール。
gem install --local <gemファイルパス>
Gemfileを適当に修正して、bundle install/update などする。
で、再度実行すると、タイムアウトにかかることなく処理が完了した。
但し、処理時間が倍くらい(30分弱)かかるようになった。
※ちなみに、同じデータをクラウドのMongoDB(Herokuアドオンの『mLab MongoDB』)に移行したときは、トータル8時間ほどかかった。
クラウドへの移行は、一旦ローカルのMongoDBに移行して、そこから mongodump/mongorestore
でクラウドに移行するのをお薦め。
> bundle exec mongify process mlab.config translation_fix.rb
DL is deprecated, please use Fiddle
DL is deprecated, please use Fiddle
Copying xxxxxxx (1/1): (163/163) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:01
Copying xxxxxxx (1/1): (1088/1088) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:03
Copying xxxxxxx (1/3): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:22
Copying xxxxxxx (2/3): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:20
Copying xxxxxxx (3/3): (1815/1815) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:03
Copying xxxxxxx (1/3): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:20
Copying xxxxxxx (2/3): (10000/10000) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:20
Copying xxxxxxx (3/3): (6010/6010) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:12
Updating References xxxxx: (163/163) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:00
Updating References xxxxx: (1088/1088) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:07
Updating References xxxxx: (21815/21815) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 03:02:28
Updating References xxxxx: (26010/26010) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 04:31:40
Removing pre_mongified_id xxxxxx: (1/1) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:00
Removing pre_mongified_id xxxxxx: (1/1) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:00
Removing pre_mongified_id xxxxxx: (1/1) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:01
Removing pre_mongified_id xxxxxx: (1/1) 100% |ooooooooooooooooooooooooooooooooooooooooooooo| Time: 00:00:01
※ちなみにちなみに、DBサイズは PostgreSQLの時は約8MBだったが、MongoDBに移行したら約16MBになった。
確認
意図した通りにtranslationされているかどうかを必ず確認すること。
- referrence/embedが正しく行われているか(先頭のデータだけではなく、末尾のデータまで確認が必要)
- オリジナルのidが必要ならちゃんとそれを残しているか
- 不要なカラムを移行してきていないか