Liquibase

LiquiBase是一个用于数据库重构和迁移的开源工具,通过日志文件的形式记录数据库的变更,然后执行日志文件中的修改,将数据库更新或回滚到一致的状态。LiquiBase的主要特点有:

  • 支持几乎所有主流的数据库,如MySQL, PostgreSQL, Oracle, Sql Server, DB2等;
  • 支持多开发者的协作维护;
  • 日志文件支持多种格式,如XML, YAML, JSON, SQL等;
  • 支持多种运行方式,如命令行、Spring集成、Maven插件、Gradle插件等;

 

changelog文件格式

changelog是LiquiBase用来记录数据库的变更,一般放在CLASSPATH下,然后配置到执行路径中。
changelog支持多种格式,主要有XML/JSON/YAML/SQL,其中XML/JSON/YAML除了具体格式语法不同,节点配置很类似,SQL格式中主要记录SQL语句,这里仅给出XML格式和SQL格式的示例,更多的格式示例请参考文档

changelog.xml

复制代码
<changeSet author="admin" id="1496901181769-1">
    <createTable schemaName="ihome" tableName="test">
        <column autoIncrement="true" name="id" type="INT">
            <constraints primaryKey="true"/>
        </column>
        <column name="name" type="VARCHAR(10)"/>
    </createTable>
</changeSet>
复制代码

 

changelog.sql

复制代码
--liquibase formatted sql
--changeset daniel:16040707
CREATE TABLE `role_authority_sum` (
  `row_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
  `role_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '关联role的role_id',
  `authority_sum` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'perms的值的和',
  `data_type_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '关联data_type的id',
  PRIMARY KEY (`row_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色的权限值的和,如角色有RD权限,则和为2+8=10';
复制代码

 

在执行changelog的时候,会在数据库记录执行记录,主要用了下面的两张表:

  1. databasechangelog
  2. databasechangeloglock

 

常用的标签及命令

1. 标签

一个<changeSet>标签对应一个变更集,由属性id、name,以及changelog的文件路径唯一标识。changelog在执行的时候并不是按照id的顺序,而是按照changeSet在changelog中出现的顺序。

changelog中的一个changeSet对应一个事务,在changeSet执行完后commit,如果出现错误则rollback。

 

2. <include>与<includeAll>标签

<include>的file属性表示要包含的changelog文件的路径,这个文件可以是LiquiBase支持的任意格式,relativeToChangelogFile如果为true,则表示file属性表示的文件路径是相对于根changelog而不是CLASSPATH的,默认为false。
<includeAll>指定的是changelog的目录,而不是为文件,如:

<includeAll path="com/example/changelogs/"/>

 

注意: 目前<include>没有解决重复引用和循环引用的问题,重复引用还好,LiquiBase在执行的时候可以判断重复,而循环引用会导致无限循环,需要注意!

 

3. 生成已有数据库的changelog

有两种方式,一种是使用数据库工具导出SQL数据,然后changelog文件以SQL格式记录即可;另一种方式就是用generateChangeLog命令,如:

复制代码
liquibase --driver=com.mysql.jdbc.Driver \
      --classpath=./mysql-connector-java-5.1.29.jar \
      --changeLogFile=liquibase/db.changelog.xml \
      --url="jdbc:mysql://127.0.0.1:3306/test" \
      --username=root \
      --password=yourpass \
      generateChangeLog
复制代码

 

不过generateChangeLog不支持以下功能:存储过程、函数以及触发器;

 

生成文件的路径可以设置:

复制代码
<plugin>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-maven-plugin</artifactId>
    <version>3.4.2</version>
    <configuration>
        <propertyFile>src/main/resources/liquibase.properties</propertyFile>
        <propertyFileWillOverride>true</propertyFileWillOverride>
        <!--生成文件的路径-->
        <outputChangeLogFile>src/main/resources/changelog_dev.xml</outputChangeLogFile>
    </configuration>
</plugin>
复制代码

 

也可以配置在properties文件中:

复制代码
changeLogFile=src/main/resources/db/changelog/db.changelog-master.xml
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&useSSL=false&jdbcCompliantTruncation=false
username=root
password=123456
verbose=true
## 生成文件的路径
outputChangeLogFile=src/main/resources/changelog_dev.xml
复制代码

 

 

Maven集成

liquibase-maven-plugin的配置

如果需要在父项目中配置子项目共享的LiquiBase配置,而各个子项目可以定义自己的配置,并覆盖父项目中的配置,则只需要在父项目的pom中将propertyFileWillOverride设置为true即可,如:

复制代码
<plugin>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-maven-plugin</artifactId>
    <version>3.4.2</version>
    <configuration>
        <propertyFileWillOverride>true</propertyFileWillOverride>
        <propertyFile>src/main/resources/liquibase.properties</propertyFile>
    </configuration>
</plugin>
复制代码
复制代码
## 执行changelog中的变更
liquibase:update

## rollback
liquibase:rollback

rollback有3中形式,分别是:
- rollbackCount: 表示rollback的changeset的个数;
- rollbackDate:表示rollback到指定的日期;
- rollbackTag:表示rollback到指定的tag,需要使用LiquiBase在具体的时间点打上tag;

liquibase:rollback -Dliquibase.rollbackCount=3

rollbackDate需要注意日期的格式,必须匹配当前平台上执行DateFormat.getDateInstance()得到的格式,比如我的格式为MMM d, yyyy,示例如:
liquibase:rollback -Dliquibase.rollbackDate="Apr 10, 2016"

rollbackTag使用tag标识,所以需要先打tag,示例如:
liquibase:tag -Dliquibase.tag=tag20160410

然后rollback到tag20160410,如:
liquibase:rollback -Dliquibase.rollbackTag=tag20160410
复制代码

 

最佳实践

1. 如何管理changeLogs

按照主要的release版本号管理你的changeLogs

复制代码
com
  example
    db
      changelog
        db.changelog-master.xml
        db.changelog-1.0.xml
        db.changelog-1.1.xml
        db.changelog-2.0.xml
      DatabasePool.java
      AbstractDAO.java
复制代码

 

db.changelog-master.xml

该文件包含了所有的release版本的changeLog,并按照正确的顺序引入进来:

复制代码
<?xml version="1.0" encoding="UTF-8"?> 
<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-3.1.xsd">

  <include file="com/example/db/changelog/db.changelog-1.0.xml"/> 
  <include file="com/example/db/changelog/db.changelog-1.1.xml"/> 
  <include file="com/example/db/changelog/db.changelog-2.0.xml"/> 
</databaseChangeLog> 
复制代码

 

 

2. Managing Stored Procedures
Try to maintain separate changelog for Stored Procedures and use runOnChange=”true”. This flag forces LiquiBase to check if the changeset was modified. If so, liquibase executes the change again.

 

 

3. One Change per ChangeSet
As far as possible, Avoid multiple changes per changeset to avoid failed autocommit statements that can leave the database in an unexpected state

4. ChangeSet Ids
Choose what works for you. Some use a sequence number starting from 1 and unique within the changelog, some choose a descriptive name (e.g. ‘new-address-table’).

5. Document ChangeSets
Use <comments> in the change sets. They say “A stitch in time saves nine!”

6. Always think about rollback
Try to write changesets in a way that they can be rolled back. e.g. use relevant change clause instead of using custom <sql> tag. Include a <rollback> clause whenever a change doesn’t support out of box rollback. (e.g. <sql>, <insert>, etc)

7. Reference Data Management
Leverage Liquibase to manage your Reference Data. Environment separation (DEV, QA, PROD) can be achieved using “context”. 

8. Procedure for the developer

  • Using your favorite IDE or editor, create a new local changeSet containing the change;
  • Run Liquibase to execute the new changeSet (this tests the SQL code);
  • Perform the corresponding changes in the application code (e.g., Java code);
  • Test the new application code together with the database change;
  • Commit both the changeSet and the application code.

 

 

问题

'changeLogFile' in properties file is not being used by this task.

 

 

链接

posted @ 2022-10-27 15:34  牧之丨  阅读(858)  评论(0编辑  收藏  举报