概要
Go製のマイグレーションツールであるsql-migrateに入門したのでまとめていきます。
複数のマイグレーションファイルを使用した時の動作や、複数の実行環境を分ける動作も検証を行ったので参考になればと思います。
最後に、sql-migrateを選んだ理由についても記述しましたので、興味がありましたらご覧ください。
実行環境
$ go version
go version go1.15.4 darwin/amd64
$ docker -v
Docker version 20.10.6
$ docker-compose -version
docker-compose version 1.29.1
試してみる
最終的には以下のディレクトリ構成になりました。
$ tree
.
├── Dockerfile
├── dbconfig.yml
├── docker-compose.yml
├── migrations
│ ├── 20210704224341-create_users.sql
│ ├── 20210704230246-add_name_to_users.sql
│ └── 20210704231016-add_age_to_users.sql
└── tmp
sql-migrateのインストール
$ go get -v github.com/rubenv/sql-migrate/...
Dockerで環境を作る
Dockerを利用してMySQLの実行環境を整えます。
version: "3"
services:
db:
image: mysql:5.7
ports:
- "3306:3306"
environment:
MYSQL_ROOT_USER: root
MYSQL_ROOT_PASSWORD: mysql
データベースを作る
コンテナの中に入ってDBを作成します。環境別での動作も検証したいので、2つDBを作成します。
$ docker-compose up -d
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ba6dc3787946 mysql:5.7 "docker-entrypoint.s…" 6 seconds ago Up 2 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp sql-migrate_db_1
$ docker exec -it sql-migrate_db_1 bash
root@29e7d071a9fc:/# mysql -u root -p --host 127.0.0.1
mysql> create database sql_migrate_dev;
mysql> create database sql_migrate_stg;
設定ファイルを書く
development:
dialect: mysql
datasource: root:mysql@tcp(127.0.0.1)/sql_migrate_dev?parseTime=true
dir: ./migrations/
staging:
dialect: mysql
datasource: root:mysql@tcp(127.0.0.1)/sql_migrate_stg?parseTime=true
dir: ./migrations/
これで使用する準備は完了です。
マイグレーションファイルを作成する
マイグレーションファイルはsql-migrate new
で作成します。
$ sql-migrate new create_users
Created migration migrations/20210704224341-create_users.sql
作成したマイグレーションファイルの中身は以下の内容に変更します。
-- +migrate Up
CREATE TABLE IF NOT EXISTS users (id int);
-- +migrate Down
DROP TABLE IF EXISTS users;
マイグレーションを実行する
マイグレーションを実行するにはsql-migrate up
を使用します。
使用できるすべてのマイグレーションファイルを読み込みます。
$ sql-migrate up
Applied 1 migration
statusを確認する
statusを確認するには、sql-migrate status
を使用します。
$ sql-migrate status
+---------------------------------+-------------------------------+
| MIGRATION | APPLIED |
+---------------------------------+-------------------------------+
| 20210704224341-create_users.sql | 2021-07-04 13:57:40 +0000 UTC |
+---------------------------------+-------------------------------+
usersテーブルが作成されていることが確認出来ます。
mysql> use sql_migrate_dev
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_sql_migrate_dev |
+---------------------------+
| gorp_migrations |
| users |
+---------------------------+
2 rows in set (0.00 sec)
1つバージョンを下げる
sql-migrate down
を使用することでバージョンを下げることが出来ます。
downは1回ごとに1バージョン下がります。
$ sql-migrate down
Applied 1 migration
$ sql-migrate status
+---------------------------------+---------+
| MIGRATION | APPLIED |
+---------------------------------+---------+
| 20210704224341-create_users.sql | no |
+---------------------------------+---------+
テーブルが無くなりました。
mysql> show tables;
+---------------------------+
| Tables_in_sql_migrate_dev |
+---------------------------+
| gorp_migrations |
+---------------------------+
1 row in set (0.00 sec)
3つのマイグレーションファイルで試してみる
新たに2つマイグレーションファイルを作成します。
$ sql-migrate new add_name_to_users
Created migration migrations/20210704230246-add_name_to_users.sql
$ sql-migrate new add_age_to_users
Created migration migrations/20210704231016-add_age_to_users.sql
-- +migrate Up
ALTER TABLE users ADD COLUMN name varchar(10);
-- +migrate Down
ALTER TABLE users DROP COLUMN name;
-- +migrate Up
ALTER TABLE users ADD COLUMN age int;
-- +migrate Down
ALTER TABLE users DROP COLUMN age;
一度の実行で、すべてマイグレーションファイルが読み込めていることが確認出来ます。
$ sql-migrate up
Applied 3 migrations
$ sql-migrate status
+--------------------------------------+-------------------------------+
| MIGRATION | APPLIED |
+--------------------------------------+-------------------------------+
| 20210704224341-create_users.sql | 2021-07-04 14:11:40 +0000 UTC |
| 20210704230246-add_name_to_users.sql | 2021-07-04 14:11:40 +0000 UTC |
| 20210704231016-add_age_to_users.sql | 2021-07-04 14:11:40 +0000 UTC |
+--------------------------------------+-------------------------------+
新たに、nameとageが作成されました。
mysql> show columns from users;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(10) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
指定したバージョン数切り戻す
limitオプションを使用することで、複数バージョン切り戻すことが出来ます。
$ sql-migrate down -limit=2
Applied 2 migrations
$ sql-migrate status
+--------------------------------------+-------------------------------+
| MIGRATION | APPLIED |
+--------------------------------------+-------------------------------+
| 20210704224341-create_users.sql | 2021-07-04 14:11:40 +0000 UTC |
| 20210704230246-add_name_to_users.sql | no |
| 20210704231016-add_age_to_users.sql | no |
+--------------------------------------+-------------------------------+
別環境で実行してみる
envオプションを使用することで、実行環境を分けることが出来ます。envオプションを指定しない場合は、developmentの設定内容が使用されます。
$ sql-migrate up -env="staging"
Applied 3 migrations
$ sql-migrate status -env="staging"
+--------------------------------------+-------------------------------+
| MIGRATION | APPLIED |
+--------------------------------------+-------------------------------+
| 20210704224341-create_users.sql | 2021-07-04 14:20:13 +0000 UTC |
| 20210704230246-add_name_to_users.sql | 2021-07-04 14:20:13 +0000 UTC |
| 20210704231016-add_age_to_users.sql | 2021-07-04 14:20:13 +0000 UTC |
+--------------------------------------+-------------------------------+
mysql> use sql_migrate_stg
Database changed
mysql> show columns from users;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(10) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
これで、一通りの機能は網羅できたと思います。
[番外編] なぜsql-migrateを選んだか
Go製のマイグレーションツールには、golang-migrate/migrateやgoose、GORMといった複数の選択肢があります。最初に、その中でsql-migrateを選んだ理由をお話できればと思います。
まず、利用するマイグレーションツールには以下の条件を求めていました。
- CLIが利用できること
- upとdownができること
- statusなどが見やすく表示されること
- 2021年時点でアップデートされていること
これらの条件を加味した結果、残ったのが以下の2つです。
次に、それぞれのメリットを調査しました。
sql-migrateを使うメリット
sql-migrateでは設定ファイルを利用することが出来、実行環境を分けることが容易です。
一方で、gooseでは設定ファイルの利用が出来ません。
(厳密には、現在更新されているGitHub版では利用できず、更新が止まっているBitbucket版では利用可能なようです。)
gooseを使うメリット
gooseは、特定のバージョンを指定してmigrate出来ます。
$ goose up-to 20170506082420
一方で、sql-migrateは-limit
オプションを使用することで複数バージョンdownしたりup出来ます。
$ sql-migrate down -limit=2
人にもよるとは思いますが、個人的にはバージョン指定出来る方が便利だなと感じています。
結局、sql-migrateを選んだ
設定ファイルが無いとめんどくさいよね、ということでsql-migrateを選びました。
なお、選定には以下の記事を大いに参考にさせていただきました。
結局 go の migration ツールは何を使えばよいのか
以上です。