LoginSignup
2
3

More than 5 years have passed since last update.

mongify を使って MySQL から MongoDB にデータ移行

Last updated at Posted at 2016-10-16

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を。環境によってはもっと色々記述する必要がある。

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 をコピーした。

接続設定ファイルの作成

database.config(ファイル名は何でもOK)
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が必要ならちゃんとそれを残しているか
  • 不要なカラムを移行してきていないか

参考

mongifyの公式 getting started ページ ※コンパクトにまとまっていて分かりやすい

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3