kamimai — Go言語製DBマイグレーションツールの紹介

eureka, Inc.
Eureka Engineering
Published in
7 min readNov 29, 2016

Pairs事業部の田野です。


Go言語のコミュニティも盛り上がってきており、あちらこちらで「Go言語を採用した!」という話を直接伺うことが多くなってきました。

Go言語製ツールの検討

エウレカもGo言語を使いはじめて2年ほどが経過しました。Go言語導入当初に色々なGo言語製のツールを検討したのですが、マイグレーションツールはそのうちの一つでした。


その調べた内容を「Go製マイグレーションツールの現状確認」というプレゼンテーションとして当時の勉強会で発表しました。

マイグレーションツールの要点

当時の状況を考えると、Go言語製のマイグレーションツールは業務に利用するには辛いライブラリが多かったです。

  1. MySQLのサポートがない
  2. マイグレーションのUp/Downの概念 がない
  3. 環境毎のマイグレーションを実行するのに、環境毎のフォルダを生成してSQL文ファイルを分割する必要がある
  4. ファイル名のプレフィックスで実行するか/しないかを判定する。よって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&...&paramN=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をお待ちしております!

--

--

eureka, Inc.
Eureka Engineering

Learn more about how Eureka technology and engineering