flyway備忘録

flywayとは?

DBのスキーマ変更をバージョン管理するツール。

DDLとDML呼ばれるSQLファイルを作成し、コマンドラインでMigrationすることでDBを変更する。

DDL

Data Definition Language。スキーマの定義や変更(CREATE、ALTER、DROP、TRUNCATE)を管理する。バージョンをインクリメントして整合性を保つ。

DML

Data Manipulation Language。マスタデータを更新(INSERT、UPDATE、DELETE、SELECT)する。バージョン管理はしない。

機能

指定変数の使用

DDL、DML内で変数を使用したい場合、placeholders機能を使用する。

build.gradle に以下のように記述する。

flyway {
    placeholders = [
        'apl': 'APL_PROD',
        'host': 'HST_PROD'
    ]
}

上記の例で、DDL内で${val1}と記述すると、APL_PRODが代入される。

Appendix

flyway_schema_historyはどこに配置するべき?

flyway_schema_historyテーブルは管理者にしか見えないようにするべきか、それなら別のスキーマにするべきか、など迷うことがあると思う。

基本的には自分のスキーマに作成し、アプリ用ユーザーで管理するのがベストプラクティス。

特に保守では、リリース日の異なる複数案件を同時開発するので、DDLの順序が途中で変わったりするケースもよくある。

そのときに、flyway_schema_historyを、管理者ではなく開発者レベルで修正することがあるため。

僕のプロジェクトは少し特殊で、CI/CDにJenkinsを使用し、管理者ユーザーによって複数環境をデプロイさせる必要があったため、各環境それぞれ、flyway_schema_historyを管理するためだけのスキーマを用意し、管理者は横ぐしでアクセスできるような構成を取っていた。

flyway_schema_history がどこにあるか調べる

SELECT owner, table_name
FROM all_tables
WHERE table_name LIKE 'flyway_%';

インシデント

Detected resolved migration not applied to database: XXX

flywayMigrate実行時エラー

> Task : flywayMigrate
Caching disabled for task ':flywayMigrate' because;
  Build cache is disabled
Task flywayMigrate' is not up-to-date because:
  Task has not declared any outputs despite executing actions.

* What went wrong:
Execution failed for task ': flywayMigrate'.
  > Error occurred while executing flywayMigrate
    Validate failed:
  Detected resolved migration not applied to database: 00.000.563
  Detected resolved migration not applied to database: 00.000.564
  Detected resolved migration not applied to database: 00.000.565
  Detected resolved migration not applied to database: 00.000.566
  Detected resolved migration not applied to database: 00.000.567

以下のコマンドを実行して、定義ファイルをチェックする

gradlew flywayValidate

以下の条件でFAILEDとなる。

  • 『flyway_schema_history』と『定義ファイル』のtypeとchecksumが不一致
  • 『build.gradle の target』と『Schema version』が不一致

>FAILEしたので定義ファイルがおかしい

flywayMigrate実行ログを見てみると、以下のエラー。

Detected resolved migration not applied to database: 00.000.XXX  // データベースに適用されていない解決済みの移行が検出されました

flyway Infoで見たところ、実行履歴の一部がIgnoreとなっており、これらが無視されているため順序がおかしいとのエラーが出ているよう。

scheme_historyを修正する_方法1

手順は複雑だが、何が起きているかわかりやすいのでまずはこちらで解説する。

とにかく簡単に解消だけしたい場合は方法2を参照。

flywayのバージョンはscheme_historyというテーブルで管理されているので、このテーブルを修正する。

例えば、バージョン100と200でMigrate済みのスキーマに、バージョン150のDDLを追加してMigrateしようとすると、150がIgnoreとなる。 以下の手順で解消する。

scheme_historyに接続し、バージョン200のレコードを削除する。

flywayMigrate実行すると、バージョン150は通るが、以下のエラーとなる。

ORA-00955: name is already used by an existing object  // ORA-00955: すでに使用されているオブジェクト名です

バージョン200はすでに実行済みのため、同じテーブルを作ろうとしてエラーとなっている。

scheme_historyのバージョン200のレコードを見ると、success カラムが0となっているので、これを1に変えてあげる。

scheme_historyを修正する_方法2

flywayInfoで、Ignoreとなっているhistoryレコードを削除(バックアップはしておく)し、flywayMigrateを再実行する。

Migration checksum mismatch for migration version 00.000.XXX

flywayMigrate実行時エラー。

flywayRepairで修復可能。

ORA-01031

新しいスキーマにはじめてflywayMigrateを実行した際のエラー。

CREATE TABLE などの基本的な権限はユーザーに付与してある。

エラーメッセージ

Caused by: org.flywaydb.core.internal.exception.FlywaySqlException:
Unable to create schema "schemaXX"
SQL State: 42000
Error Code: 1031
Message: ORA-01031: 権限が不足しています
~~~ ~~~
  at org.flywaydb.core.internal.database.base.Schema.create(Schema.java:118)
  ... 160 more
Caused by: Error: 1031, Position: 0, Sql = CREATE USER "schemaXX" IDENTIFIED BY OriginalSql = CREATE USER "schemaXX" IDENTIFIED BY "FFllyywwaayyoo!!", Error Msg = ORA-01031: 権限が不足しています
  at oracle.jdbc.driver.T4CTTloer11.processError(T4CTTloer11.java:513)

なぜか CREATE USER を使おうとしている、つまりは新しいスキーマを作ろうとしてしまっている。

flywayの設定(build.gradle)で、スキーマ名の指定が間違っている場合、flywayは新規スキーマとして作成しようとするためこのエラーが起こる。

build.gradleのスキーマ指定箇所を見てみると、大文字で記載されるべきスキーマ名が小文字になっていたので、大文字に変更して解消した。

Found non-empty schema(s)

flyway実行前にテーブルにデータ移行したため、 空でないスキーマにflywayは実行でき
ないと怒られている。

すべてのテーブルをDROPして再実行し解消。

ORA-01031: 権限が不足しています

flywayInfoは実行できるが、flywayMigrateを実行しようとするとタイトルのエラーが発生する。

これは、ユーザーにCREATE、ALTER等の実行権限が不足しているために起きる。

Oracle Database SQL備忘録-権限設定』を参考に、自身のユーザーのロールや権限を確認する。

flyway_schema_history に SQL でアクセスできない

以下のSQLでflyway_schema_historyにアクセスしようとしたが、テーブルが見つからない。

select * from flyway_schema_history;

テーブル名を以下のようにダブルクオーテーションで囲わないと、大文字に変換されてしまい、テーブルを検知できない。

select * from "flyway_schema_history";

 

コメント

タイトルとURLをコピーしました