flyway使ってるの初めて見て良く分からん感じだったのでとりあえずチュートリアル https://flywaydb.org/getstarted/ を読んで訳した。
※画像はすべて本家のものです。
Why database migrations?
まず最初にShinyというプロジェクトを仮定し、ここでの成果物の一つはShiny SoftというソフトウェアでこれはShiny DBというDBに接続します。
これを簡単に図示すると以下のようになります。
他にもソフトウェアとDBが存在します。ここまでは良いでしょう。
しかし大半のプロジェクトにおいて、そのシンプルな世界観は急速に以下のように変貌します。
環境のコピーを一回した程度では収まらず複数管理する必要が出てきます。このことは様々な課題を生み出します。
ソースコードの世界ではこれに上手く対処してきました。
- 今日のバージョン管理は普遍的なツールになっています。
- 繰り返し実行可能なビルドと継続的なインテグレーションが可能です。
- 優れたリリースとデプロイ処理を行えます。
データベースの世界ではどうでしょうか?
今のところこれを上手くやることは出来ていません。たいていのプロジェクトでは未だに手動でSQLスクリプトを適用しています。時にはそれすらありません(問題を修正するためのその場限りのSQLが散在するなど)。ここで色々な疑問が浮かんできます。
- あるマシン上のDBはどうなっているのか?
- このスクリプトは適用済みなのか?そうでないのか?
- 本番環境で流した緊急修正は後でテスト環境にも適用したのか?
- データベースのインスタンスのセットアップ手順は?
基本的にはこれらの問いに対して我々は回答を持ち合わせていません。
データベースマイグレーションとはこうした混乱した状況の制御を取り戻すための有効な手段です。
これにより以下が可能となります。
- スクラッチからデータベースを再作成。
- データベースの状態が常に明確となる。
- DBの現行バージョンから新バージョンへ決定論的な方法で移行する。
How Flyway works
最もシンプルなシナリオでは空のDBにFlywayを立てる場合です。
Flywayはschema history tableを参照しようとします。データベースは空なのでFlywayは参照できず代わりに生成します。
デフォルトではflyway_schema_historyという一つの空のテーブルがDBに作られます。
このテーブルがDBの状態をトラッキングするのに使われます。
この後Flywayはファイルシステムかアプリケーションのクラスパスをマイグレーションのためにスキャンします。マイグレーションはJavaかSQLのどちらかで書きます。
マイグレーションはバージョン番号でソートされており順番に適用されます。
個々のマイグレーションが適用されるたびに、schema history tableもそれに応じて更新されます。
以下はflyway_schema_historyの例です。
installed_rank | version | description | type | script | checksum | installed_by | installed_on | execution_time | success |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | Initial Setup | SQL | V1__Initial_Setup.sql | 1996767037 | axel | 2016-02-04 22:23:00.0 | 546 | true |
2 | 2 | First Changes | SQL | V2__First_Changes.sql | 1279644856 | axel | 2016-02-06 09:18:00.0 | 127 | true |
メタデータと初期状態を配置し終えたので、次に新バージョンへのマイグレーションについて説明します。
Flywaryは再度ファイルシステムかアプリケーションのクラスパスをマイグレーションのためにスキャンします。マイグレーションはschema history tableとの照らし合わしを行います。バージョン番号が現行と等しいか低い場合、そのマイグレーションは無視されます。
それ以外のマイグレーションはpending migrationsになります。これは、適用可能ではあるがまだ適用されていない、という意味です。
マイグレーションはバージョン番号でソートされて順に実行されます。
schema history tableはそれに応じて更新されます。
flyway_schema_historyは以下のようになります。
installed_rank | version | description | type | script | checksum | installed_by | installed_on | execution_time | success |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | Initial Setup | SQL | V1__Initial_Setup.sql | 1996767037 | axel | 2016-02-04 22:23:00.0 | 546 | true |
2 | 2 | First Changes | SQL | V2__First_Changes.sql | 1279644856 | axel | 2016-02-06 09:18:00.0 | 127 | true |
3 | 2.1 | Refactoring | JDBC | V2_1__Refactoring | axel | 2016-02-10 17:45:05.4 | 251 | true |
以上が一連の流れになります。データベースを更新する場合、DDLでもDMLでも、新規のマイグレーションを作成してバージョン番号を現行よりも高いものにします。それからFlywayを起動すると、そのマイグレーションでDBを更新します。
First Steps: Command-line
以下のカンタンなチュートリアルではFlywayのCLIでの使い方を解説します。設定方法と、最初のDBマイグレーションの書き方と動かし方が書いてあります。
このチュートリアルの所要時間はおおむね5分程度です。
Downloading and extracting Flyway
プラットフォームに応じたdownloading the Flyway Command-line ToolをDLして解凍します。
出来たディレクトリに移動します。
cd flyway-5.0.7
cd flyway-5.0.7
次に、以下のような/conf/flyway.conf
を編集してFlywayを設定します。
flyway.url=jdbc:h2:file:./foobardb flyway.user=SA flyway.password=
Creating the first migration
/sql
ディレクトリにV1__Create_person_table.sql
という一つ目のマイグレーションを作成します。
create table PERSON ( ID int not null, NAME varchar(100) not null );
Migrating the database
DBをマイグレーションするためにFlywayを実行します。
flyway-5.0.7> flyway migrate
実行後、以下のような出力が得られます。
Database: jdbc:h2:file:./foobardb (H2 1.4) Successfully validated 1 migration (execution time 00:00.008s) Creating Schema History table: "PUBLIC"."flyway_schema_history" Current version of schema "PUBLIC": << Empty Schema >> Migrating schema "PUBLIC" to version 1 - Create person table Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.033s)
Adding a second migration
次に、二つ目のマイグレーションV2__Add_people.sql
を/sql
ディレクトリに追加します。
insert into PERSON (ID, NAME) values (1, 'Axel'); insert into PERSON (ID, NAME) values (2, 'Mr. Foo'); insert into PERSON (ID, NAME) values (3, 'Ms. Bar');
これを発行するためにFlywayを実行します。
flyway-5.0.7> flyway migrate
以下のような実行結果になります。
Database: jdbc:h2:file:./foobardb (H2 1.4) Successfully validated 2 migrations (execution time 00:00.018s) Current version of schema "PUBLIC": 1 Migrating schema "PUBLIC" to version 2 - Add people Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.016s)
Summary
このチュートリアルでは以下について触れました。
マイグレーションが正常に実行されたのを確認できました。
First Steps: API
Prerequisites
Creating the project
以下のコマンドでMaven Archetype Pluginを使用してプロジェクトを生成します。
> mvn archetype:generate -B ^ -DarchetypeGroupId=org.apache.maven.archetypes ^ -DarchetypeArtifactId=maven-archetype-quickstart ^ -DarchetypeVersion=1.1 ^ -DgroupId=foo ^ -DartifactId=bar ^ -Dversion=1.0-SNAPSHOT ^ -Dpackage=foobar
準備が出来たのでプロジェクトのディレクトリに移動します。
> cd bar
Adding the dependencies
pom.xml
にFlywayとH2を追加します。
<project ...> ... <dependencies> <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> <version>5.0.7</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.3.170</version> </dependency> ... </dependencies> ... </project>
Integrating Flyway
src/main/java/foobar/App.java
でFlywayとの連携をするためにDBと接続するコードを書きます。
package foobar; import org.flywaydb.core.Flyway; public class App { public static void main(String[] args) { // Flywayインスタンスの生成 Flyway flyway = new Flyway(); // DB接続 flyway.setDataSource("jdbc:h2:file:./target/foobar", "sa", null); // マイグレーション開始 flyway.migrate(); } }
Creating the first migration
src/main/resources/db/migration
というマイグレーションディレクトリを作成します。以下のようにsrc/main/resources/db/migration/V1__Create_person_table.sql
という最初のマイグレーションを作ります。
create table PERSON ( ID int not null, NAME varchar(100) not null );
Executing our program
以下コマンドによりプログラムを実行します。
bar> mvn package exec:java -Dexec.mainClass=foobar.App
実行後、以下のような出力が得られます(タイムスタンプは消してあります)
INFO: Creating schema history table: "PUBLIC"."flyway_schema_history" INFO: Current version of schema "PUBLIC": << Empty Schema >> INFO: Migrating schema "PUBLIC" to version 1 - Create person table INFO: Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.062s).
Adding a second migration
次のマイグレーションを追加するのにsrc/main/resources/db/migration/V2__Add_people.sql
を作ります。
insert into PERSON (ID, NAME) values (1, 'Axel'); insert into PERSON (ID, NAME) values (2, 'Mr. Foo'); insert into PERSON (ID, NAME) values (3, 'Ms. Bar');
以下で実行します。
bar> mvn package exec:java -Dexec.mainClass=foobar.App
以下のようになります。
INFO: Current version of schema "PUBLIC": 1 INFO: Migrating schema "PUBLIC" to version 2 - Add people INFO: Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.090s).
このチュートリアルでは以下について解説しました。
- プロジェクトとFlywayを連携させる
- DBと接続するための設定
- 一組のマイグレーションの作成
マイグレーションが正常に実行されたのを確認できました。
First Steps: Gradle
Prerequisites
- Java 8 or 9
- Gradle 3.0 or newer
Setting up the build file
FlywayとH2に接続する設定と連携するbuild.gradle
を作成します。
buildscript { dependencies { classpath 'com.h2database:h2:1.4.191' } } plugins { id "org.flywaydb.flyway" version "5.0.7" } flyway { url = 'jdbc:h2:file:./target/foobar' user = 'sa' }
Creating the first migration
src/main/resources/db/migration/V1__Create_person_table.sql
という最初のマイグレーションを作ります。
create table PERSON ( ID int not null, NAME varchar(100) not null );
Migrating the database
DBをマイグレートするためにFlywayを実行します。
> gradle flywayMigrate -i
実行後、以下のような出力になります。
Creating schema history table: "PUBLIC"."flyway_schema_history" Current version of schema "PUBLIC": << Empty Schema >> Migrating schema "PUBLIC" to version 1 - Create person table Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.062s).
Adding a second migration
二つ目のマイグレーションsrc/main/resources/db/migration/V2__Add_people.sql
を追加します。
insert into PERSON (ID, NAME) values (1, 'Axel'); insert into PERSON (ID, NAME) values (2, 'Mr. Foo'); insert into PERSON (ID, NAME) values (3, 'Ms. Bar');
以下で実行します。
> gradle flywayMigrate -i
以下のような出力になります。
Current version of schema "PUBLIC": 1 Migrating schema "PUBLIC" to version 2 - Add people Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.090s).
このチュートリアルでは以下について解説しました。
マイグレーションが正常に実行されたのを確認できました。
First Steps: Maven
(似たような内容なんで省略)