Liquibaseを使用したデータベース移行管理

少し前に、Liquibaseを、新規および既存のほとんどのプロジェクトでデータスキーマ移行ツールとして導入し始めました。 Liquibaseデータベーススキーマ移行システムは、バージョン管理システムであるVCS(Gitなど)を使用してアプリケーションデータベースのリビジョンを管理できるため、優れています。 より具体的には、VCSはデータベーススキーマをあるリビジョンから別のリビジョンに移行するために必要な変更を記述します。



データベーススキーマの移行は、最初は非常に単純なタスクのように見えますが、スキーマを再作成せずにスキーマへの変更をロールバックすると、タスクはより困難になります。

Liquibaseでは、DDLスキーマと操作に加えて、データ変更のロールとロールバックのサポートにより、アプリケーションデータを移行できます。



簡単に始めましょう。 この記事で説明する例では、コマンドラインから実行するLiquibaseと、MySQL用のシンプルなCLIクライアントを使用します。

Liquibaseは、Maven(目標として)またはSpring(コンテキストの初期化中に実行されるBean)とも統合します。



ID(主キー)と名前のみで構成される非常に単純なPERSONテーブルから始めましょう。



mysql> describe Person; +-------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | name | varchar(255) | NO | UNI | NULL | | +-------+--------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec)
      
      







Liquibaseは、いわゆる "changeset"(changeset-変更セット)XMLコードを使用してDDLステートメントを記述します。 変更ログファイルを作成します。 次のチェンジャーは、テーブル(タグ "createTable")と2つの列(タグ "column")を作成します。



 <databasechangelog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd"> <changeset id="1" author="mueller@synyx.de" runonchange="true"> <createtable tablename="Person"> <column autoincrement="true" name="id" type="BIGINT"> <constraints nullable="false" primarykey="true"> </constraints> </column> <column name="name" type="VARCHAR(255)"> <constraints nullable="false"> </constraints> </column> </createtable> </changeset> </databasechangelog>
      
      







このXMLコードを使用して、Liquibaseは「Person」テーブルを追加します。 コマンドラインインターフェイスからこれを実行するコマンドは「update」です。



 ./liquibase --url=jdbc:mysql://localhost:3306/liquiblog --driver=com.mysql.jdbc.Driver --username=root --password="" --changeLogFile=db.changelog-0.1.0.xml update
      
      







Liquibaseには、createTableなど、一部のタイプの変更ヒントをロールバックするための組み込みサポートがあります。 引数「update」ではなく「rollbackCount 1」を指定してコマンドラインからLiquibaseを呼び出すと、最後のチェンジャーがロールバックされ、PERSONテーブルが削除されます。



他のタイプのチェンジャーセットは自動的に削除できません。 例として、PERSON(「挿入」タグ)にデータを追加する次のチェンジャーセットを考えます。



 <databasechangelog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd"> <changeset id="init-1" author="mueller@synyx.de"> <insert tablename="Person"> <column name="name" value="John Doe"> </column> </insert> <rollback> DELETE FROM Person WHERE name LIKE 'John Doe'; </rollback> </changeset> </databasechangelog>
      
      







このチェンジャーへの変更をロールバックするSQLステートメントを含む「ロールバック」タグを手動で追加しました。 このタグには、SQLステートメントと通常のLiquibaseタグの両方を含めることができます。

現在、2つのXML変更ログファイルがあるので、データベースの正しいリビジョンを取得するために必要な順序で他のファイルをインポートする「メイン」ファイルを作成しました。



 <databasechangelog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd"> <include file="db.changelog-0.1.0.xml"></include> <include file="db.changelog-0.1.0.init.xml"></include> </databasechangelog>
      
      







各チェンジャーセットに対して「update」コマンドが呼び出されると、それが回路に適用されているかどうかがチェックされます。 チェンジャーがまだ適用されていない場合、実行されます。 これを行うために、LiquibaseはデータをDATABASECHANGELOGS補助テーブルに保存します。このテーブルには、すでに使用されているチャンギエットとそのハッシュ値が含まれています。 ハッシュは、すでに完了したchangetosetsを変更できないように使用されます。



 mysql> select id, md5sum, description from DATABASECHANGELOG; +--------+------------------------------------+--------------+ | id | md5sum | description | +--------+------------------------------------+--------------+ | 1 | 3:5a36f447e90b35c3802cb6fe16cb12a7 | Create Table | | init-1 | 3:43c29e0011ebfcfd9cfbbb8450179a41 | Insert Row | +--------+------------------------------------+--------------+ 2 rows in set (0.00 sec)
      
      







簡単な例が機能したので、もっと複雑なことを試してみましょう。スキーマの変更には、スキーマの移行とデータの更新が必要です。 PERSONテーブルには現在、NAMEという名前の列しかありません。NAMEを2つの列(FIRSTNAMEとLASTNAME)に分割します。 データベースの移行を開始する前に、将来このタグへのすべての変更をロールバックできるように、Liquibaseの「タグ」を配置します。



 ./liquibase --url=jdbc:mysql://localhost:3306/liquiblog --driver=com.mysql.jdbc.Driver --username=root --password="" --changeLogFile=changelog-master.xml tag liquiblog_0_1_0
      
      







2つの新しい列を追加する新しいチェンジャーを作成しました。



 <changeset id="1" author="mueller@synyx.de" runonchange="true"> <addcolumn tablename="Person"> <column name="firstname" type="VARCHAR(255)"> <constraints nullable="false"> </constraints> </column> <column name="lastname" type="VARCHAR(255)"> <constraints nullable="false"> </constraints> </column> </addcolumn> </changeset>
      
      







そして今回、Liquibaseはこのchangetsetをロールバックする方法を知っているため、「rollback」タグを追加することはできません。



現在、PERSONテーブルには2つの追加列があり、古いNAME列を削除する前に、既存のデータを新しいスキーマに移行する必要があります。 Liquibaseはデータ操作をすぐにサポートしていないため、チェンジャーにネイティブSQLを含めるにはsqlタグを使用する必要があります。



 <changeset author="mueller@synyx.de" id="2"> <sql> UPDATE Person SET firstname = SUBSTRING_INDEX(name, ' ', 1); UPDATE Person SET lastname = SUBSTRING_INDEX(name, ' ', -1); </sql> <rollback> UPDATE Person SET firstname = ''; UPDATE Person SET lastname = ''; </rollback> </changeset>
      
      







「ロールバック」タグの内容は冗長に見えますが、Liquibaseではチェンジャーのロールバックのみが許可されているため、タグ自体が必要であることに注意してください。





「更新」オプションでLiquibaseを起動すると、新しいチェンジャーがスキームに適用されます。作成された列FIRSTNAMEとLASTNAMEにはすでにデータが含まれています。



次に、古いNAME列を削除します。



 <changeset id="3" author="mueller@synyx.de" runonchange="true"> <dropcolumn tablename="Person" columnname="name"> </dropcolumn> <rollback> <addcolumn tablename="Person"> <column name="name" type="VARCHAR(255)"> <constraints nullable="false"> </constraints> </column> </addcolumn> <sql> UPDATE Person SET name = CONCAT(firstname, CONCAT(' ', lastname)); </sql> </rollback> </changeset>
      
      







Liquibaseは列の削除をサポートしているため、チェンジャー自体は非常に単純ですが、ロールバックタグはより複雑になりました。

  1. 標準タグ「addColumn」を使用して、古い列NAMEを再追加します
  2. SQLステートメントを使用して、この列のデータを回復します




変換結果:



 mysql> select * from Person; +----+-----------+------------+ | id | firstname | lastname | +----+-----------+------------+ | 1 | John | Doe | +----+-----------+------------+ 1 rows in set (0.00 sec)
      
      







最初にタグでスキーマにタグを付け、すべてのチェンジャーセットで変更をロールバックするための指示を追加したという事実により、データを失うことなくデータベーススキーマの変更をロールバックできます! 呼び出し中...



 ./liquibase --url=jdbc:mysql://localhost:3306/liquiblog --driver=com.mysql.jdbc.Driver --username=root --password="" --changeLogFile=changelog-master.xml rollback liquiblog_0_1_0
      
      







...データベーススキーマの状態に戻りました!



PERSONという名前の文字列の分割/マージの例は多少不自然ですが、同じ原則をより深刻なデータ変更に適用できます。

既存のドメインクラス(1つのテーブルに対応)を、データの整合性を維持する必要性を考慮して、抽象基本クラスと2つのサブクラスの3つの部分に分割する作業中に、この投稿のアイデアに出会いました。



All Articles