LoginSignup
2

More than 1 year has passed since last update.

posted at

updated at

Go製マイグレーションツールのsql-migrateを一通り試した

概要

Go製のマイグレーションツールであるsql-migrateに入門したのでまとめていきます。
複数のマイグレーションファイルを使用した時の動作や、複数の実行環境を分ける動作も検証を行ったので参考になればと思います。
最後に、sql-migrateを選んだ理由についても記述しましたので、興味がありましたらご覧ください。

実行環境

terminal
$ 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のインストール

terminal
$ go get -v github.com/rubenv/sql-migrate/...

Dockerで環境を作る

Dockerを利用してMySQLの実行環境を整えます。

docker-compose.yml
 version: "3"
 services:
   db:
     image: mysql:5.7
     ports:
       - "3306:3306"
     environment:
       MYSQL_ROOT_USER: root
       MYSQL_ROOT_PASSWORD: mysql

データベースを作る

コンテナの中に入ってDBを作成します。環境別での動作も検証したいので、2つDBを作成します。

terminal
$ 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;

設定ファイルを書く

dbconfig.yml
 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で作成します。

terminal
 $ sql-migrate new create_users
 Created migration migrations/20210704224341-create_users.sql

作成したマイグレーションファイルの中身は以下の内容に変更します。

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を使用します。
使用できるすべてのマイグレーションファイルを読み込みます。

terminal
 $ sql-migrate up 
 Applied 1 migration

statusを確認する

statusを確認するには、sql-migrate statusを使用します。

terminal
 $ sql-migrate status
 +---------------------------------+-------------------------------+
 |            MIGRATION            |            APPLIED            |
 +---------------------------------+-------------------------------+
 | 20210704224341-create_users.sql | 2021-07-04 13:57:40 +0000 UTC |
 +---------------------------------+-------------------------------+

usersテーブルが作成されていることが確認出来ます。

terminal
 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バージョン下がります。

terminal
 $ sql-migrate down
 Applied 1 migration
    $ sql-migrate status
 +---------------------------------+---------+
 |            MIGRATION            | APPLIED |
 +---------------------------------+---------+
 | 20210704224341-create_users.sql | no      |
 +---------------------------------+---------+

テーブルが無くなりました。

terminal
 mysql> show tables;
 +---------------------------+
 | Tables_in_sql_migrate_dev |
 +---------------------------+
 | gorp_migrations           |
 +---------------------------+
 1 row in set (0.00 sec)

3つのマイグレーションファイルで試してみる

新たに2つマイグレーションファイルを作成します。

terminal
 $ 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
migrations/20210704230246-add_name_to_users.sq
 -- +migrate Up
 ALTER TABLE users ADD COLUMN name varchar(10);

 -- +migrate Down
 ALTER TABLE users DROP COLUMN name;
migrations/20210704231016-add_age_to_users.sq
 -- +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が作成されました。

terminal
 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オプションを使用することで、複数バージョン切り戻すことが出来ます。

terminal
 $ 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の設定内容が使用されます。

terminal
 $ 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 |
 +--------------------------------------+-------------------------------+
terminal
 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/migrategooseGORMといった複数の選択肢があります。最初に、その中で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 ツールは何を使えばよいのか

以上です。

参考

結局 go の migration ツールは何を使えばよいのか

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
What you can do with signing up
2