読者です 読者をやめる 読者になる 読者になる

256bitの殺人メニュー

インフラエンジニアだったソリューションアーキテクトなくわののブログ。こちらのBlogは個人の意見となっていて会社とは全く関係ありません。お約束です。[twitter:@kuwa_tw]めんどくさがりが重い腰を上げて何かをアウトプットすることにどれほどの意味があるのかを試してみたいブログでもある。

シェルスクリプトだけでMySQLからMongoDBへの移行しちゃう

このエントリは、MySQL Casual Advent Calendar 23日目のエントリです。

どうもどうも乙カレー様です。桑野です。
お酒が入ってるとわけわかんないことをいうことがおおいんですが(ごめんなさい)
さてブログ書こうと思ってアドベントカレンダーのページ見なおしたらなんか書いてあるんですよね。

MySQLだっつってんだろ。
ということで何書こうかなと思ってたんですが、ネタ記事としてシェルスクリプトだけでMySQLからMongoDBへの移行しちゃうのをやろうかと思います。
誰得なのかということであれば俺得です(∗ᵒ̶̶̷̀ω˂̶́∗)੭₎₎̊₊♡ウケトレィ!


と言うかなんか怒られそう、、、ごめんなさいごめんなさいネタが思いつかなかったんですホントですm(_ _)m

ちゅーわけでテストテーブル作ってみる。

まずは移行元のMySQLにテーブル作ってみましょ。
適当に。

mysql> CREATE DATABASE d1;
mysql> use d1
mysql>  CREATE TABLE t1 (
   id INT PRIMARY KEY AUTO_INCREMENT,
   name VARCHAR(20),
   nosql VARCHAR(30),
   price INT UNSIGNED,
   created_at DATETIME
 );
mysql>  INSERT INTO t1 (name, nosql, price, created_at)
   VALUES ("kuwa_tw", "mongodb", 10, now());
mysql> INSERT INTO t1 (name, nosql, price, created_at)
   VALUES ("oranie", "cassandra", 100, now());
mysql> INSERT INTO t1 (name, nosql, price, created_at)
   VALUES ("kakky_h", "hbase", 1000, now());
mysql> INSERT INTO t1 (name, nosql, price, created_at)
   VALUES ("la_luna_azul", "riak", 1500, now());
mysql> INSERT INTO t1 (name, nosql, price, created_at)
   VALUES ("saeoshi", "voldemote", 2000, now());
 mysql> SELECT * FROM t1;
 +----+--------------+-----------+-------+---------------------+
 | id | name         | nosql     | price | created_at          |
 +----+--------------+-----------+-------+---------------------+
 |  1 | kuwa_tw      | mongodb   |    10 | 2014-12-23 21:14:39 |
 |  2 | oranie       | cassandra |   100 | 2014-12-23 21:14:40 |
 |  3 | kakky_h      | hbase     |  1000 | 2014-12-23 21:14:41 |
 |  4 | la_luna_azul | riak      |  1500 | 2014-12-23 21:14:42 |
 |  5 | saeoshi      | voldemote |  2000 | 2014-12-23 21:14:43 |
 +----+--------------+-----------+-------+---------------------+
 5 rows in set (0.00 sec)

ほいできました。

移行しましょう。

MySQLのデータをCSV出力

シェルスクリプトというか、まずはCSV出力でしましょ。

$ mysql -h localhost -u root -p pass d1 -e "SELECT * FROM t1" | tr "\t" "," >> ./dump.sql

全テーブルやりたかったらforで回したりしたらいいんじゃないですかね!

$ for t in `mysql -h localhost -u root  d1 -e "show tables from mysql;" | awk 'NR!=1{ print $1}'`
do
   mysql -h localhost -u root -p pass d1 -e "SELECT * FROM ${t}" | tr "\t" "," >> ./dump_${t}.sql
done

こんなのが出ました。

 cat dump.csv
 id,name,nosql,price,created_at
 1,kuwa_tw,mongodb,10,2014-12-23 21:14:39
 2,oranie,cassandra,100,2014-12-23 21:14:40
 3,kakky_h,hbase,1000,2014-12-23 21:14:41
 4,la_luna_azul,riak,1500,2014-12-23 21:14:42
 5,saeoshi,voldemote,2000,2014-12-23 21:14:43
CSV出力を修正

これでもうMongoDB食わせられるんですが、DateがStringになっちゃってるので変換してみましょう。
MongoDBのextended json formatのページを参照に修正してみましょう(CSVだけど)

$ awk -F, -v OFS=, 'NR!=1{tmp="ISODate(\""substr($5,1,10)"T"substr($5,12,9)"+0900""\")";$NF="";print $0tmp ; next} NR=1{print $0}' dump.csv  > dump_fix.csv
 id,name,nosql,price,created_at
 1,kuwa_tw,mongodb,10,ISODate("2014-12-23T21:14:39+0900")
 2,oranie,cassandra,100,ISODate("2014-12-23T21:14:40+0900")
 3,kakky_h,hbase,1000,ISODate("2014-12-23T21:14:41+0900")
 4,la_luna_azul,riak,1500,ISODate("2014-12-23T21:14:42+0900")
 5,saeoshi,voldemote,2000,ISODate("2014-12-23T21:14:43+0900")

こうなったら成功です。

MongoDB へのインポート

最後はmongoimportコマンドでMongoDBにいれるだけ!

$ mongoimport --host localhost --port 27018 -d d1 -c t1 --type csv --file dump_fix.csv --headerline --drop
connected to: localhost:27018
2014-12-23T22:34:53.535+0900 dropping: d1.t1
2014-12-23T22:34:53.539+0900 imported 5 objects
  • mongoimportのオプションの意味
    • --host 接続先ホスト
    • --port 接続先ポート
    • -d database
    • -c collection
    • --file 読み込むファイル
    • --type ファイルタイプ
    • --hederline 最初の行をヘッダとして見る(フィールド名になる)
    • --drop インポート前にコレクションをDROPする(若干危険)

入った入った!クララも立った!
、、、と言うことでデータみてみましょう。

$ mongo --host localhost --port 27018
 MongoDB shell version: 2.6.4
 connecting to: localhost:27018/test
 > use d1
 switched to db d1
 > db.t1.find()
 { "_id" : ObjectId("54996816e0035c426fd71b2c"), "id" : 1, "name" : "kuwa_tw", "nosql" : "mongodb", "price" : 10, "created_at" : "2014-12-23T21:14:39+0900" }
 { "_id" : ObjectId("54996816e0035c426fd71b2d"), "id" : 2, "name" : "oranie", "nosql" : "cassandra", "price" : 100, "created_at" : "2014-12-23T21:14:40+0900" }
 { "_id" : ObjectId("54996816e0035c426fd71b2e"), "id" : 3, "name" : "kakky_h", "nosql" : "hbase", "price" : 1000, "created_at" : "2014-12-23T21:14:41+0900" }
 { "_id" : ObjectId("54996816e0035c426fd71b2f"), "id" : 4, "name" : "la_luna_azul", "nosql" : "riak", "price" : 1500, "created_at" : "2014-12-23T21:14:42+0900" }
 { "_id" : ObjectId("54996816e0035c426fd71b30"), "id" : 5, "name" : "saeoshi", "nosql" : "voldemote", "price" : 2000, "created_at" : "2014-12-23T21:14:43+0900" }

どうでしょう。はいっております。これは奇跡。
ということでありまして、MySQLからMongoDBに移行したい、なんていう珍しい方がおりましたら是非こんな感じで試してみてはいかがでしょうか。


ただし責任は取れませんが、、、(怪談的な終わり方)


追記

で、締まったかと思ったんですが、、、すいません、、、上記の方法でもISODateでは入ってませんでした、、、。

変換する場合はmongo shellに入って、

db.t1.find({ },{ "created_at": 1 }).forEach(function(document){

    var newDate = ISODate( document.created_at );

    db.t1.update(
        { _id: document._id },
        { "$set": { "created_at": newDate } }
    );
})

という感じでできると思います、、、シェルスクリプトだけでできてないしなんなのこれ、、、もう、、、。

> db.t1.find()
{ "_id" : ObjectId("54998426e0035c426fd71b7b"), "id" : 1, "name" : "kuwa_tw", "nosql" : "mongodb", "price" : 10, "created_at" : ISODate("2014-12-23T12:14:39Z") }
{ "_id" : ObjectId("54998426e0035c426fd71b7c"), "id" : 2, "name" : "oranie", "nosql" : "cassandra", "price" : 100, "created_at" : ISODate("2014-12-23T21:14:40Z") }
{ "_id" : ObjectId("54998426e0035c426fd71b7d"), "id" : 3, "name" : "kakky_h", "nosql" : "hbase", "price" : 1000, "created_at" : ISODate("2014-12-23T21:14:41Z") }
{ "_id" : ObjectId("54998426e0035c426fd71b7e"), "id" : 4, "name" : "la_luna_azul", "nosql" : "riak", "price" : 1500, "created_at" : ISODate("2014-12-23T21:14:42Z") }
{ "_id" : ObjectId("54998426e0035c426fd71b7f"), "id" : 5, "name" : "saeoshi", "nosql" : "voldemote", "price" : 2000, "created_at" : ISODate("2014-12-23T21:14:43Z") }

というわけで、これでOKですm(_ _)m


エキスパートのためのMySQL[運用+管理]トラブルシューティングガイド

エキスパートのためのMySQL[運用+管理]トラブルシューティングガイド



MongoDBイン・アクション

MongoDBイン・アクション