Flywayを触ってみる(コマンドライン)

はじめに

データベースマイグレーションツールの一つであるFlywayを触ってみます。
業務で使用しているものの、私がやっていることはDBに変更があった際のマイグレーションファイルを作成する程度なので、改めて使用方法などを整理できればと思います。

なお、私の仕事上ではSpring bootと併用していますが、今回はSpringプロジェクトを作成するほどのことでもないので、コマンドライン上でのお試しとします。
Springとの併用はそのうちやります・・。

マイグレーションとは

データベースの変更を記録することで、データベースの変更を容易にするためのもの・・と理解しています。

やってみる

Flywayも、他のツールに漏れず公式ドキュメントが充実しているので、そちらを参考に実施していきます。

インストール

先述したように、今回はコマンドツールを用いてFlywayを利用していきます。
また、今回は学習用ですので、Community Edition(無料)をインストールします。 こちらから、適宜環境にあったものをダウンロードしましょう。

FlywayをPATHに通す

FlywayをPATHに通します。私はfishというシェルを使用しているため、~/.config/fish/config.fishに以下の記述を追記しました。

set PATH /Users/ochiaisho/devTools/flyway-7.8.2 $PATH

zshや、bashなど、各自の環境に合わせてPATHを通すようにしましょう。

flyway.confの修正

データベース接続情報をconf/flyway.confに記述します。
私の場合は以下のようになります。

flyway.url=jdbc:mysql://localhost:3306/flyway
flyway.user=root
flyway.password=password

マイグレーションファイルの作成

実際にデータベースへ反映するためのマイグレーションファイルを作成します。
今回は、新しくUserというテーブルを作成するDDLを追加します。

create table USER (
    ID int not null,
    NAME varchar(100) not null
);

ここまでで、準備はあらかた終了です。

flyway migrate

それでは実際にflyway migrateを実行してみましょう。

$ flyway migrate

成功すると、以下のようなレスポンスとなります。
(バージョンやデータベース名などは適宜読み替えてください。)

Flyway Community Edition 7.8.2 by Redgate
Database: jdbc:mysql://localhost:3306/flyway (MySQL 8.0)
Successfully validated 1 migration (execution time 00:00.017s)
Creating Schema History table `flyway`.`flyway_schema_history` ...
Current version of schema `flyway`: << Empty Schema >>
Migrating schema `flyway` to version "1 - create user"
Successfully applied 1 migration to schema `flyway`, now at version v1 (execution time 00:00.040s)

成功すると、Userテーブルと、flyway_schema_historyというテーブルが作成されます。

mysql> show tables;
+-----------------------+
| Tables_in_flyway      |
+-----------------------+
| flyway_schema_history |
| USER                  |
+-----------------------+
2 rows in set (0.00 sec)

Userテーブルは自分で作成したテーブルなのでいいとして、flyway_schema_historyというテーブルはなんなのでしょうか?
ということで、もう少し続けます。

flyway_schema_historyとは

平たく言うと、flyway_schema_historyはテーブルのマイグレーション(変更)の記録を保持するテーブルとなります。 見てみる方が早いと思いますので、とりあえず作成されたテーブルの中身を調べてみることにしましょう。

mysql> select * from flyway_schema_history;
+----------------+---------+-------------+------+---------------------+------------+--------------+---------------------+----------------+---------+
| installed_rank | version | description | type | script              | checksum   | installed_by | installed_on        | execution_time | success |
+----------------+---------+-------------+------+---------------------+------------+--------------+---------------------+----------------+---------+
|              1 | 1       | create user | SQL  | V1__create_user.sql | 1761476051 | root         | 2021-05-09 14:48:27 |             10 |       1 |
+----------------+---------+-------------+------+---------------------+------------+--------------+---------------------+----------------+---------+
1 row in set (0.00 sec)

今回、Userというテーブルを作成した履歴が残っているのがわかるかと思います。
履歴が残るということを確認したいので、試しに別のテーブルを作成してみましょう。

マイグレーションファイルを追加する

今回も、テーブル追加のためのマイグレーションファイルを作成しようと思います。
sqlディレクトリ配下に、V2__create_second_table.sqlというファイル名で、適当なテーブルを作成しようと思います。

create table SECOND_TABLE(
    ID int not null,
);            

ファイルが作成できたら、再度flyway migrateを実行してみます。

$ flyway migrate

成功すると以下のようなメッセージが返ってきます。

Flyway Community Edition 7.8.2 by Redgate
Database: jdbc:mysql://localhost:3306/flyway (MySQL 8.0)
Successfully validated 2 migrations (execution time 00:00.018s)
Current version of schema `flyway`: 1
Migrating schema `flyway` to version "2 - create second table"
Successfully applied 1 migration to schema `flyway`, now at version v2 (execution time 00:00.050s)

この状態で再度データベースの状態を確認してみましょう。

mysql> show tables;
+-----------------------+
| Tables_in_flyway      |
+-----------------------+
| flyway_schema_history |
| SECOND_TABLE          |
| USER                  |
+-----------------------+
3 rows in set (0.00 sec)

show tablesで確認すると、SECOND_TABLEが作成されていることがわかりますね。
次に、flyway_schema_historyの中身も確認してみましょう。

mysql> select * from flyway_schema_history;
+----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+
| installed_rank | version | description         | type | script                      | checksum   | installed_by | installed_on        | execution_time | success |
+----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+
|              1 | 1       | create user         | SQL  | V1__create_user.sql         | 1761476051 | root         | 2021-05-09 14:48:27 |             10 |       1 |
|              2 | 2       | create second table | SQL  | V2__create_second_table.sql |  942681622 | root         | 2021-05-09 15:17:43 |             15 |       1 |
+----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+
2 rows in set (0.00 sec)

レコードが追加されていますね。

このような形で、Flywayが実行したマイグレーションの履歴がどんどん積み重なっていくことになります。

おまけ

実はSECOND_TABLEを追加しようとしたところ、sql syntax errorが発生したため、マイグレーションに失敗した、という事象が発生していました。
そこで、SQLを修正し、再度flyway migrateを実行したところ、さらに別のエラーが発生・・ということも発生したんですね。つまり、

  1. flyway migrateで、sql の文法エラーが発生
  2. sqlファイルの修正
  3. flyway migrateでさらにエラーが発生

という流れです。この時のエラー解消方法を念のため記録しておこうと思います。

エラー内容

まずは実際のエラー内容から。
(なお、実際はsql syntax errorも出ていましたが、直接Flywayとは関係ないので割愛しています。)

ERROR: Validate failed: Migrations have failed validation
Detected failed migration to version 2 (create second table). Please remove any half-completed changes then run repair to fix the schema history.
Need more flexibility with validation rules? Learn more: https://flywaydb.org/custom-validate-rules

Please remove any half-completed changes then run repair to fix the schema history.ということなので、不完全な状態の変更を削除してから再実行するのが正しいようです。 ここで、上記の1.でエラーが発生した直後のflyway_schema_historyを確認してみます。

+----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+
| installed_rank | version | description         | type | script                      | checksum   | installed_by | installed_on        | execution_time | success |
+----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+
|              1 | 1       | create user         | SQL  | V1__create_user.sql         | 1761476051 | root         | 2021-05-09 14:48:27 |             10 |       1 |
|              2 | 2       | create second table | SQL  | V2__create_second_table.sql | -371576338 | root         | 2021-05-09 15:15:48 |             17 |       0 |
+----------------+---------+---------------------+------+-----------------------------+------------+--------------+---------------------+----------------+---------+

実は、マイグレーションに失敗しても、flyway_schema_historyにレコードは追加されます。
ここでさらにレコードの内容をみてみると、successというカラムがマイグレーションの成否を表すカラムであることに気づくと思います。
1が成功、0が失敗ですね。 そこで、マイグレーションに失敗しているレコードであるsuccess=0のレコードを削除してから再度flyway migrateを実行することでエラーが解消され、マイグレーションが成功しました。

終わりに

マイグレーションツールを使用すれば、データベースに対する変更が正しい順序で反映されるので、ちゃんと使用できれば便利ですね。今回はやりませんでしたが、例えばカラムの削除・カラム定義の変更など、テーブルの初期状態からの変化を正しい順序で実行していくというのは手作業ではどうしても難しいシーンもあると思いますので、そういったことへの対策にもなりそうです。