はじめに
業務では専らMySQLを使用している。
スキーマ管理として、migrateを用いており、この使用方法をメモ。
環境
- migrate v4.14.1
- MySQL 5.7
インストール
下記本家サイトを参考にインストールしておく。
OptionとCommand
migrate -help
で確認できるが、OptionとCommandは以下のような感じ。
Options:
-source Location of the migrations (driver://url)
-path Shorthand for -source=file://path
-database Run migrations against this database (driver://url)
-prefetch N Number of migrations to load in advance before executing (default 10)
-lock-timeout N Allow N seconds to acquire database lock (default 15)
-verbose Print verbose logging
-version Print version
-help Print usage
Commands:
create [-ext E] [-dir D] [-seq] [-digits N] [-format] NAME
Create a set of timestamped up/down migrations titled NAME, in directory D with extension E.
Use -seq option to generate sequential up/down migrations with N digits.
Use -format option to specify a Go time format string. Note: migrations with the same time cause "duplicate migration version" error.
goto V Migrate to version V
up [N] Apply all or N up migrations
down [N] Apply all or N down migrations
drop [-f] [-all] Drop everything inside database
Use -f to bypass confirmation
Use -all to apply all down migrations
force V Set version V but don't run migration (ignores dirty state)
version Print current migration version
使い方
以下のコマンドを実行すると、0001_secual.up.sql
と0001_secual.down.sql
のファイルが作成される。
migrate create -ext sql -seq -digits 4 secual
以下のコマンドだと、202108171914_secual.up.sql
と202108171914_secual.down.sql
が作成される。
migrate create -ext sql -format 200601021504 secual
-
*.up.sql
と対になる*.down.sql
が必要 - ファイル名先頭は数値(0パディング)、もしくは
yyyyMMddHHmm
のような日付形式(この値でバージョン管理される)
中身(例1)
*.up.sql
には、DBスキーマに適用したい内容を書く。例えば、テーブル作成。
CREATE TABLE article (
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(50),
content TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
*.down.sql
には、*.up.sql
を打ち消す内容を書く。例えば、*.up.sql
がテーブル作成であればテーブル削除。
DROP TABLE article;
中身(例2)
例えば、カラム変更とカラム追加の場合。
ALTER TABLE article MODIFY COLUMN title VARCHAR(100);
ALTER TABLE article ADD COLUMN author VARCHAR(50) AFTER content;
*.down.sql
には、カラム削除とカラム変更。(*.up.sql
の記載と逆の順番で、*.down.sql
に記載するようにしている。整合性がとりやすいので。)
ALTER TABLE article DROP COLUMN author;
ALTER TABLE article MODIFY COLUMN title VARCHAR(50);
実行
バージョン確認
*.up.sql
や*.down.sql
があるディレクトリだと、以下のコマンドで現在のmigrateのバージョンが確認できる。
migrate -source file://./ -database 'mysql://user:passwd@tcp(localhost:3306)/media' version
-
-source
で、*.up.sql
や*.down.sql
のディレクトリを指定 -
-database
で、接続するデータベースを指定
0002_secual.up.sql
まで適用されている場合は、2
と表示される。
アップ適用
*.up.sql
の内容を適用するには、以下のコマンドを実行する。
migrate -source file://./ -database 'mysql://user:passwd@tcp(localhost:3306)/media' up
適用されていない *.up.sql の内容がすべて適用される。(最大バージョンまで適用される。)
例えば、現在のバージョンが 0001 であり、0004_secual.up.sqlまで作成されている場合、0002→0003→0004の順ですべてが適用される。
現在のバージョンが1
であり、0004_secual.up.sql
まで作成されているが、0003_secual.up.sql
までを適用したい場合(2つバージョンを上げたい場合)は、以下のコマンドを実行する。
migrate -source file://./ -database 'mysql://user:passwd@tcp(localhost:3306)/media' up 2
ダウン適用
*.down.sql
の内容を適用するには、以下のコマンドを実行する。
migrate -source file://./ -database 'mysql://user:passwd@tcp(localhost:3306)/media' down
最小バージョン(0001_secual.down.sql)までの内容がすべて適用される。
現在のバージョンが4
であり、0002_secual.down.sql
までを適用したい場合(2つバージョンを下げたい場合)は、以下のコマンドを実行する。
migrate -source file://./ -database 'mysql://user:passwd@tcp(localhost:3306)/media' down 2
強制的にバージョン変更
強制的にバージョンを2
に変更する場合には以下のコマンドを実行する。主にアップ(up)やダウン(down)でエラーになった場合に用いる。
migrate -source file://./ -database 'mysql://user:passwd@tcp(localhost:3306)/media' force 2
migrateのバージョンのみを変えるだけであって、アップ(up)やダウン(down)のSQLは実行されないので、DBスキーマは不整合性な状態になっているはず。この場合は、SQLを別途実行して調整する必要がある。
例えば、以下のようなSQL(ADDのtypo)でアップ(up)した場合、1行目のMODIFYは実行され2行目でエラーになる。
ALTER TABLE article MODIFY COLUMN title VARCHAR(100);
ALTER TABLE article AD COLUMN author VARCHAR(50) AFTER content;
migrateのバージョンは、1(dirty)
となる。以下のような対処が必要になる。
-
ALTER TABLE article ADD COLUMN author VARCHAR(50) AFTER content;
を実行し正しいバージョン2
の状態にして、migrateコマンドでforce 2
を実行する -
ALTER TABLE article MODIFY COLUMN title VARCHAR(50);
を実行しバージョン1
の状態に戻して、migrateコマンドでforce 1
を実行する
運用するにあたり
- バージョンとして数値と日付を選択できるが、数値のほうが管理しやすい(日付バージョンで運用したことないけど。。)
- 面倒だけど、順序はそれぞれで逆になるように、upとdownは対になるように書く
- 1ファイルに多くを記述するのではなく、テーブル単位などで細かくファイルを分けるようにする(エラー時に対応が面倒になるので。。)
- ファイルは記述した人がローカル環境などで動作確認しておくべし
- ファイル名でバージョン管理することになるためGitとの相性が悪い。。(複数人がNASで共有編集する運用をしてます。。他に何かいいツールありますか?)