最近、社内で「継続的デリバリー」の読書会をやっています。
AWSなど簡単・迅速にインフラを調達できる時代になり、デプロイメントパイプラインを早い段階で構築することができる環境が整ったんだなぁと改めて実感します。
デプロイメントパイプラインを作るために欠かせないことの1つが、DBの構成管理です。
以前DBの構成管理をしていなかったために、リリース作業自体に時間がかかったり、リリースバグを出したことのある人も多いのではないでしょうか。(私も経験してます...)
今回は、JavaのDBマイグレーションツールを2つ試してみました。
FlywayとLiquibaseです。すでに、ここにFlywayとLiquibaseの比較記事がありますが、自分の感想を書きます。
1. インストール・環境構築について
FlywayとLiquibaseもインストールの手間はそれほど変わりません。
今回は、コマンドライン版で試してみました。
また、OS、Java、DBの環境は以下です。
OS : MacOS Lion
Java : 1.7.0_21
DB : PostgreSQL 9.2.4
JDBCドライバは、ここから適当なものをダウンロードすればOKです。
1.1 Flywayのインストール
ここから、「flyway-commandline-2.2.tar.gz」をダウンロードして、展開します。
mkdir flyway_work cd flyway_work wget http://repo1.maven.org/maven2/com/googlecode/flyway/flyway-commandline/2.2/flyway-commandline-2.2.tar.gz tar xvfz flyway-commandline-2.2.tar.gz cd flyway-2.2 chmod 755 flyway
JDBCドライバをjarsディレクトリに配置します。
設定ファイル(flyway.properties.org)をflyway.propertiesという名前でコピーします。
cp conf/flyway.properties.org conf/flyway.properties
flyway.propertiesを開き、下記項目を編集します。
(以下、最低限の設定です。)
flyway.url=jdbc:postgresql://[DBサーバーIP]/[database名] flyway.user=[DBユーザ名] flyway.password=[DBパスワード]
Flywayでは、DBマイグレーション処理は、下記のようにファイル単位でトランザクションを定義します。
vi sql/V1__Create_person_table.sql
create table PERSON ( ID int not null, NAME varchar(100) not null );
vi sql/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');
vi sql/V3__Alter_people.sql
ALTER TABLE person ADD COLUMN address text;
事前にpostgresでcreatedbします。
(例)createdb test_app
./flyway migrateを実行すると
DBの中身はこうなります。
personテーブルにすべてのSQL結果が反映されていますね。
1.2 Liquibaseのインストール
ここから、liquibase-3.0.2-bin.tar.gz をダウンロードする。
mkdir liquibase_work cd liquibase_work wget http://sourceforge.net/projects/liquibase/files/Liquibase%20Core/liquibase-3.0.2-bin.tar.gz/download tar xvfz liquibase-3.0.2-bin.tar.gz chmod 755 liquibase
上で作成したlibディレクトリの中に、JDBCドライバを入れます。
mkdir lib cd lib wget "JDBCドライバのURL"
liquibaseコマンドでDBマイグレーションを行う場合、下記必須オプションが必要です。
(必須オプション)
--changeLogFile=
driver=org.postgresql.Driver classpath=lib/postgresql-9.1-901.jdbc4.jar changeLogFile=マイグレーション処理を記述したファイル(例)db_changelog_1.sql url=JDBCのURL(例)jdbc:postgresql://localhost:5432/test_app2 username=DBユーザ名 password=DBパスワード
(複数DBMSに対応したい場合、SQL以外の選択肢があると便利ですね。さすがにストアドまでは対応してませんが...)
- XML
- YAML
- JSON
- SQL
--liquibase formatted sql --changeset hiratak:1 CREATE TABLE person ( id serial NOT NULL, -- idです。 name text, -- 名前です。 CONSTRAINT person_pkey PRIMARY KEY (id) ) WITH ( OIDS=FALSE ); ALTER TABLE person OWNER TO kzhirata; COMMENT ON TABLE person IS 'テスト用'; COMMENT ON COLUMN person.id IS 'idです。'; COMMENT ON COLUMN person.name IS '名前です。'; --rollback drop table person; --changeset hiratak:2 INSERT INTO person (name) VALUES ('やまだたろう'); INSERT INTO person (name) VALUES ('たなかはなこ'); --changeset hiratak:3 INSERT INTO person (name) VALUES ('すずきじろう'); --changeset suzuki:4 ALTER TABLE person ADD COLUMN delete_flag boolean DEFAULT false; ALTER TABLE person ALTER COLUMN delete_flag SET NOT NULL; COMMENT ON COLUMN person.delete_flag IS '削除フラグ';
Liquibaseも事前にpostgresでcreatedbします。
(例)createdb test_app2
最後に下記コマンドでmigrateします。
./liquibase migrate を実行すると
SQLの結果がすべてpersonテーブルに反映されていますね。
あと、Flywayとの違いとして、下記コマンドでHTML形式でのテーブル定義書や、SQLの更新履歴を出力することができます。
./liquibase dbDoc "HTMLファイル出力先のディレクトリパス"
作成されてHTMLをブラウザで開くと、下記のようにテーブル定義書が表示されます。
create table、alter tableでカラムを定義するときに、コメントをつければ、コメント内容がこのHTMLドキュメントにも反映されます。よく受託開発ではExcelなどでテーブル定義書を作成しますが、SQLファイルで一元管理することで、ソースとドキュメントの乖離を防ぐことができます。
複数人で開発する場合、DBスキーマもgitなどを使って各開発者で構成管理できれば、スムーズに開発できるのではないでしょうか。
長々と書いてしまいましたが、今回はこの辺で...
P.S. "flyway clean"や"liquibase dropAll"を使うときは慎重に...
./liquibase migrate を実行すると
SQLの結果がすべてpersonテーブルに反映されていますね。
あと、Flywayとの違いとして、下記コマンドでHTML形式でのテーブル定義書や、SQLの更新履歴を出力することができます。
./liquibase dbDoc "HTMLファイル出力先のディレクトリパス"
作成されてHTMLをブラウザで開くと、下記のようにテーブル定義書が表示されます。
create table、alter tableでカラムを定義するときに、コメントをつければ、コメント内容がこのHTMLドキュメントにも反映されます。よく受託開発ではExcelなどでテーブル定義書を作成しますが、SQLファイルで一元管理することで、ソースとドキュメントの乖離を防ぐことができます。
複数人で開発する場合、DBスキーマもgitなどを使って各開発者で構成管理できれば、スムーズに開発できるのではないでしょうか。
長々と書いてしまいましたが、今回はこの辺で...
P.S. "flyway clean"や"liquibase dropAll"を使うときは慎重に...