kamimai — Go言語製DBマイグレーションツールの紹介
Pairs事業部の田野です。
Go言語のコミュニティも盛り上がってきており、あちらこちらで「Go言語を採用した!」という話を直接伺うことが多くなってきました。
Go言語製ツールの検討
エウレカもGo言語を使いはじめて2年ほどが経過しました。Go言語導入当初に色々なGo言語製のツールを検討したのですが、マイグレーションツールはそのうちの一つでした。
その調べた内容を「Go製マイグレーションツールの現状確認」というプレゼンテーションとして当時の勉強会で発表しました。
マイグレーションツールの要点
当時の状況を考えると、Go言語製のマイグレーションツールは業務に利用するには辛いライブラリが多かったです。
- MySQLのサポートがない
- マイグレーションのUp/Downの概念 ※ がない
- 環境毎のマイグレーションを実行するのに、環境毎のフォルダを生成してSQL文ファイルを分割する必要がある
- ファイル名のプレフィックスで実行するか/しないかを判定する。よってmasterブランチへの反映順序でマイグレーションがスキップされるSQLがでてくる
※ Up/Downの概念: マイグレーションの実行と取り消しを操作する概念
当時、 liamstask / goose を利用していたのですが、そこから2年経過した現在でもgooseよりも上記点を解消したツールが出てきませんでした。
そこでエウレカの業務へ対応させるため、kamimai — 紙舞 と呼ばれるマイグレーションツールを作成・公開しました。
kamimai — 紙舞 の特徴
紙舞 とは 日本の妖怪をモチーフとした名前 です。kamimai
はレポジトリのREADME に記載がありますが、以下の機能があります。
- Create: UP/DOWNのマイグレーションファイルを生成する機能
- Up: 無指定もしくはファイル名指定でマイグレーションする機能
- Down: 無指定もしくはファイル名指定でマイグレーションを取り下げる機能
- Sync: 存在する全てのマイグレーションを適用する機能
また上記の機能をGo言語のコード内で実行するライブラリとしても利用いただけます。起動時にsync
を実行させるとテスト環境などで活躍してくれます。
gooseとの相違点
バージョン指定でのマイグレーションUp/Downが可能
goose
を利用しているとブランチのマージの順序によっては、ファイル名にあるタイムスタンプをリネームするまでSQLが実行されなくなるケースがあります。kamimai
ではバージョンを指定してUp/Downができるため、このような面倒な手続きがいらなくなります。
運用フェーズに入るとコードベースが重ならないように開発を工夫するでしょうし、SQLもAlter
というよりInsert
が多くなります。なので、指定実行できるマイグレーションが便利になります。goose
だとファイル名のタイムスタンプをリネームするか、特定バージョンまでDownで戻さねばなりません。
Syncコマンドで考慮漏れを解消できる
Sync
コマンドを利用すれば、存在するマイグレーションファイルのうち、未適用のものを全て適用します。例えばローカルの開発環境にてmaster
ブランチを git pull
してきたときに、何のマイグレーションが未適用かを考える必要がなく、Sync
コマンドで済んでしまうところにその良さがあります。
もちろん本番環境でこのような適用をするのは怖いので、そちらはバージョン指定でマイグレーションします。
kamimai — 紙舞の利用サンプル
以下、kamimai
の利用方法をサンプルで見ていきましょう。
インストール
kamimai
をインストールします。 glide
/ govendor
/ goenv
等、パッケージマネージャも利用可能です。
$ go get github.com/eure/kamimai/cmd/kamimai
以後 kamimai-sample
というプロジェクトで説明します。
設定ファイル作成
$ cd $GOPATH/src/path_to_your_project
$ mkdir -p misc/migrations; cd $_
$ mkdir development # 開発用マイグレーションフォルダ、名前は任意です
$ vim config.tml
config.tml
へ以下のように記載します。
[dev]
driver = "mysql"
dsn = "mysql://root:rootpassword@/kamimai-sample-db?charset=utf8"
directory = "development"
このサンプルでは1環境のみですが、複数環境分を書くことができます。
またyaml
でも設定ファイルを記述可能です。
- [dev] : 後々コマンドラインから
kamimai
を動かすときのenv
パラメータの内容です。 - driver : 利用するデータベースの名称です。現在は他のドライバーが無いため
mysql
と指定ください。 - dsn : MySQLへ接続するためのdsn文字列を指定します。記載ルールは
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
です。
参考:Go言語のmysql-driverのDSNの項目 - directory : マイグレーション用SQLのあるフォルダを指定します。
マイグレーションファイルの作成
マイグレーションファイルを作成します。
※予めmysql側へkamimai-sample-db
というデータベースを生成しておきます。
$ cd $GOPATH/src/kamimai-sample/misc/migrations
$ kamimai -env=dev -path=. create create_user_table
kamimai: created development/001_create_user_table_up.sql
kamimai: created development/001_create_user_table_down.sql
※ファイルのプレフィックスが 001
といった連番ですが、 YYYYMMDDHHMMSS
形式にリネームしておくと、次回からタイムスタンプのプレフィックスでファイルを作ります。
続いて、Up/DownのファイルへSQLを書きましょう。
Up側のSQLサンプル
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(200) DEFAULT NULL,
`age` tinyint(3) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Down側のSQLサンプル
DROP TABLE `user`;
マイグレーションの実行
マイグレーションの実行/取り消しをします。
実行(Up)
$ kamimai -env=dev -path=. up
kamimai: applied /{$GOPATHの内容}/src/kamimai-sample/misc/migrations/development/001_create_user_table_up.sql
MySQL側でテーブルが作成され、schema_version
にもバージョンが追記されていることを確認します。
取り消し(Down)
$ kamimai -env=dev -path=. down
テーブルが削除され、schema_version
からもバージョンが削除されていることを確認します。
終わりに
kamimai — 紙舞 は、まだまだ発展途上の段階です。PostgreSQL
/SQLite
のDriverが不足していたり、引数の指定を間違った時にpanicして終了するなど、利便性を高めていく開発が必要です。
kamimai - 紙舞 をご利用いただき、不足点がありましたらぜひIssueやPRをお待ちしております!