5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MySQLのmigrate

Posted at

はじめに

業務では専ら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.sql0001_secual.down.sqlのファイルが作成される。

migrate create -ext sql -seq -digits 4 secual

以下のコマンドだと、202108171914_secual.up.sql202108171914_secual.down.sqlが作成される。

migrate create -ext sql -format 200601021504 secual
  • *.up.sqlと対になる*.down.sqlが必要
  • ファイル名先頭は数値(0パディング)、もしくはyyyyMMddHHmmのような日付形式(この値でバージョン管理される)

中身(例1)

*.up.sqlには、DBスキーマに適用したい内容を書く。例えば、テーブル作成。

0001_secual.up.sql
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がテーブル作成であればテーブル削除。

0001_secual.down.sql
DROP TABLE article;

中身(例2)

例えば、カラム変更とカラム追加の場合。

0002_secual.up.sql
ALTER TABLE article MODIFY COLUMN title VARCHAR(100);
ALTER TABLE article ADD COLUMN author VARCHAR(50) AFTER content;

*.down.sqlには、カラム削除とカラム変更。(*.up.sqlの記載と逆の順番で、*.down.sqlに記載するようにしている。整合性がとりやすいので。)

0002_secual.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行目でエラーになる。

0002_secual2.up.sql
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で共有編集する運用をしてます。。他に何かいいツールありますか?)
5
3
0

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
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?