Skip to content

一、概述 ​

LiquiBase(从 2006 年开始投入使用)是一种免费开源的工具,可以实现不同数据库版本之间的迁移(参见 参考资料)。目前也存在少量其他开源数据库迁移工具,包括 openDBcopy 和 dbdeploy。LiquiBase 支持 10 种数据库类型,包括 DB2、Apache Derby、MySQL、PostgreSQL、Oracle、Microsoft®SQL Server、Sybase 和 HSQL。

通过日志文件的形式记录数据库的变更,然后执行日志文件中的修改,将数据库更新或回滚到一致的状态。它的目标是提供一种数据库类型无关的解决方案,通过执行schema类型的文件来达到迁移。

1.1 自动生成表结构 ​

-Databasechangelog:记录的是每一次表修改的记录,里面会详细记录操作的类型和操作

---Databasechangeloglock表用于确保两台计算机不会同时尝试修改数据库。

1.2 配置注意事项 ​

同一个文件中,changeSet中的id不能重复,

每次数据库变更,都会在databasechangelog生成一条记录

1.3 参考博客 ​

Liquibase高阶使用 - 东方1024 - 博客园 (cnblogs.com)

二、使用示例 ​

2.1 与springboot集成 ​

依赖 ​

xml
<!--Liquibase-->
<dependency>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-core</artifactId>
</dependency>

配置 ​

java
import liquibase.integration.spring.SpringLiquibase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.DefaultResourceLoader;

import javax.sql.DataSource;

/**
 * @Classname LiuqiubaseConfig
 * @Description TODO
 */
@Configuration
public class LiuqiubaseConfig {
    @Value("${spring.application.name}")
    private String applicationName;
    @Autowired
    private DataSource dataSource;


    @Bean("liquibase")
    public SpringLiquibase createLiquibase( ) {
        SpringLiquibase liquibase = new SpringLiquibase();
        // 用户模块Liquibase文件路径
        liquibase.setChangeLog("classpath:sql/" + applicationName + "/master.xml");
        liquibase.setDataSource(dataSource);
        liquibase.setShouldRun(true);
        liquibase.setResourceLoader(new DefaultResourceLoader());
        // 覆盖Liquibase changelog表名
        liquibase.setDatabaseChangeLogTable(applicationName + "_changelog_table");
        liquibase.setDatabaseChangeLogLockTable(applicationName + "_changelog_lock_table");
        return liquibase;
    }
}

在resorces中添加liquibase路径文件夹,然后创建changelog文件夹,在changeelog文件创建xml文件,然后书写操作数据库的sql或配置

sql脚本配置 ​

xml
<?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"
        xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
        xmlns:pro="http://www.liquibase.org/xml/ns/pro"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
		http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
		http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
		http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd">
    <!-- 将属性设置为的值  不同数据库字段标识是不一样的,语法也会有不同,通过定义属性 使用通过${}  -->
    <property  name="clob.type"  value="clob"  dbms="oracle,postgresql"/>
    <property  name="clob.type"  value="longtext"  dbms="mysql"/>
    <property  name="table.name"  value="tableA"/>

    <!-- 先决条件可以应用于整个changelog或单个changeSet。如果先决条件失败,liquibase将停止执行。  -->
    <!-- 表示数据库为Oracle,数据库的用户名为SYSTEM才允许执行上述databasechangelog  -->
    <!-- 可以使用可嵌套<and>、<or>和<not>标签将条件逻辑应用于preConditions。如果未指定条件标签,则默认为 <AND>。  -->
    <preConditions>
        <dbms type="mysql" />
        <runningAs username="root" />
    </preConditions>

    <changeSet id="1" author="Liquibase">
        <createTable tableName="test_table">
            <column name="test_id" type="int">
                <constraints primaryKey="true"/>
            </column>
            <column name="test_column" type="varchar(20)"/>
        </createTable>
    </changeSet>




    <!-- 仅当"oldtable"中没有值时,它才会运行 dropTable命令,可以防止配置错误和升级错误。
    expectedResult 这个值与SQL的执行结果作比较  -->
    <!--
    onFail: 当proConditions遇到失败的时候如何处理
    onError:当proConditions遇到错误的时候如何处理
    onUpdateSQL:自版本1.9.5后当proConditions遇到更新SQL模型的时候如何处理
    onFailMessage:自2.0起,在proConditions失败时要输出的自定义消息。
    onErrorMessage:在proConditions错误时要输出的自定义消息。
    -->
    <changeSet id="2" author="Liquibase">
        <createTable tableName="oldtable">
            <column name="test_id" type="int">
                <constraints primaryKey="true"/>
            </column>
            <column name="test_column" type="varchar(20)"/>
        </createTable>
    </changeSet>
    <changeSet id="3" author="Liquibase">
        <preConditions onFail="WARN">
            <sqlCheck expectedResult="0">select count(*) from oldtable</sqlCheck>
        </preConditions>
        <comment>Comments should go after preCondition. </comment>
        <dropTable tableName="oldtable"/>
    </changeSet>

    <!--
    1:includeAll 标签可以把一个文件夹下的所有 changelog 都加载进来。如果单个加载可以用 include。
    2:includeAll 标签里有两个属性:path 和 relativeToChangelogFile。
        2.1:path (在 include 标签里是 file):指定要加载的文件或文件夹位置
        2.2:relativeToChangelogFile :文件位置的路径是否相对于 root changelog 是相对路径,默认 false,即相对于 classpath 是相对路径。
    -->
<!--    <includeAll path="./sql/" relativeToChangelogFile="true"/>-->

    <!-- 创建表
     <createTable>表是创建表   tableName 表名
     <column>  字段标签,
        name:字段名称
        type:字段类型
        encoding:编码类型
        remarks:字段注释
    <constraints> 主键标签
        primaryKey:是否主键
        Nullable:是否为空
     -->
    <changeSet id="4" author="Liquibase">
        <createTable tableName="project_info">
            <column name="project_id" type="varchar(64)" encoding="utf8" remarks="项目id">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <column name="project_name" type="varchar(255)" encoding="utf8" remarks="项目名字"/>
        </createTable>
    </changeSet>

    <!-- 添加列
     <addColumn>  tableName 修改表名
        <column>  字段标签,
            name:字段名称
            type:字段类型
     -->
    <changeSet id="5" author="Liquibase">
        <addColumn tableName="project_info">
            <column name="address"  type="varchar(255)" encoding="utf8" remarks="地址"/>
            <column name="project_status"  type="varchar(255)" encoding="utf8" remarks="地址"/>
        </addColumn>
    </changeSet>

    <!-- 删除列
         -->
    <changeSet id="6" author="Liquibase">
        <dropColumn tableName="project_info" columnName="address"/>
    </changeSet>

    <!-- 修改表,通过sql脚本
         -->
    <changeSet id="9" author="yunshan">
        <sqlFile path="sql/liuqiubase/sql/test_stu.sql"/>
    </changeSet>

    <!-- 插入数据
    <inSert>数据插入标签
        <column>  字段标签,
            name:字段名称
            valueNumeric:对应的字符值
         -->
    <changeSet id="7" author="Liquibase">
        <insert tableName="project_info">
            <column name="project_id" valueNumeric="312223"/>
            <column name="project_status" valueNumeric="322434343"/>
            <column name="project_name" value="wkn"/>
        </insert>
    </changeSet>


    <!-- 创建索引
    <createIndex>创建索引标签
      indexName:索引名称
      tableName:表名
        <column>  name 字段标签,
         -->
    <changeSet author="Liquibase" id="8">
        <createIndex indexName="Reft_userinfo88" tableName="project_info">
            <column name="project_status"/>
        </createIndex>
    </changeSet>
</databaseChangeLog>

三、标签介绍 ​

3.1 databaseChangeLog标签 ​

liquibase的入口文件,这个标签可以引入你的版本修改文件。

xml
<?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"
        xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
        xmlns:pro="http://www.liquibase.org/xml/ns/pro"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
		http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
		http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
		http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd">
</databaseChangeLog>

子标签 ​

tagDescription
preConditions执行sql变更文件的前置条件
property设置的属性的值
changeSet要执行的更改
include包含要执行的更改集的附加文件
context上下文将被附加到(使用AND)所有变更集

3.2 preConditions标签 ​

可以应用于<databaseChangeLog>标签或者<changeSet>标签。

先决条件可以应用于整个changelog或单个changeSet。如果先决条件失败,liquibase将停止执行。

xml
<?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.8.xsd">
    <!-- 只有在Oracle数据库以及用户是SYSTEM时才会执行。-->
    <preConditions>
        <dbms type="oracle" />
        <runningAs username="SYSTEM" />
    </preConditions>
    
    <changeSet id="1" author="bob">
        <preConditions onFail="WARN">
            <sqlCheck expectedResult="0">select count(*) from oldtable</sqlCheck>
        </preConditions>
        <comment>Comments should go after preCondition. If they are before then liquibase usually gives error.</comment>
        <dropTable tableName="oldtable"/>
    </changeSet>
</databaseChangeLog>

preConditions前置条件分为正常和异常情况: 正常情况下,无论返回的值是不是预料的值(0),oldtable都会被删除,只是如果不是预料的值,这里会给出WARN; 异常情况下,也就是如果oldtable不存在,删除oldtable的命令将不会执行。

处理失败和错误 ​

AttributeDescription
onFail当preConditions是失败情形下如何处理
OnError当preConditions是错误情形下如何处理
onSqlOutput在updateSQL模式下要做什么
onFailMessage输出的失败信息
onErrorMessage输出的错误信息

OnFail/OnError值可能配置的值 ​

ValueDescription
HALT立即停止执行整个更改日志。 [默认]
CONTINUE跳过* changeSet 。 下次更新时将再次尝试执行更改集。 继续 changelog *
MARK_RAN跳过更改集,但将其标记为已执行。继续更改日志。
WARN输出警告并继续照常执行* changeSet * / * changelog *。

onSqlOutput可能配置的值 ​

ValueDescription
TEST在updateSQL模式下运行changeSet
FAIL使preConditons在updateSQL模式下失败
IGNORE忽略updateSQL模式中的preConditons(默认)。

and/or/not逻辑 ​

使用nestable <and>、<or>和<not>标记将条件逻辑应用于前置条件。如果没有指定条件标记,则默认为AND。

复合条件,例如,是oracle数据库,并且用户必须是SYSTEM 或者 数据库是mysql,且用户需要为root时

xml
<preConditions>
     <or>
         <and>
            <dbms type="oracle" />
            <runningAs username="SYSTEM" />
         </and>
         <and>
            <dbms type="mysql" />
            <runningAs username="root" />
         </and>
     </or>
 </preConditions>

可用的preConditions子标签 ​

xml
<dbms>:如果针对指定类型执行的数据库匹配,则可以传递。
<dbms type="mysql" />

<runningAs>:执行执行的用户,匹配才可以传递。
<runningAs username="root" />

<changeSetExecuted>:如果指定的changeSet被执行了才可以传递。
<changeSetExecuted id="1" author="YoungLu" changeLogFile="classpath:liquibase/changelog/2020-02-11-change.xml" />

<columnExists>:如果数据库中的指定列存在则传递
<columnExists schemaName="young_webchat" tableName="y_user" columnName="username" />

<tableExists>:如果数据库中的表存在,则传递
<tableExists schemaName="young_webchat" tableName="y_user" />

<viewExists>:如果数据库中的视图存在,则传递
<viewExists schemaName="young_webchat" viewName="y_user_view" />

<foreignKeyConstraintExists>:如果外键存在则传递
<foreignKeyConstraintExists schemaName="young_webchat" foreignKeyName="y_user_log_fk" />

<indexExists>:如果索引存在则传递
<indexExists schemaName="young_webchat" indexName="y_user_idx" />

<sequenceExists>:如果序列存在则传递
<sequenceExists schemaName="young_webchat" sequenceName="y_user_seq" />

<primaryKeyExists>:如果主键存在则传递
<primaryKeyExists schemaName="young_webchat" primaryKeyName="y_user_id" />

<sqlCheck>:执行SQL检查。SQL必须返回具有单个值的单个行。
<sqlCheck expectedResult="1">SELECT COUNT(1) FROM pg_tables WHERE TABLENAME = 'myRequiredTable'</sqlCheck>

<changeLogPropertyDefined>:检查给定的changelog参数是否存在。如果一个值也是给定的,如果这个值与给定的值不相同那么它只会失败。
<changeLogPropertyDefined property="myproperty"/>
<changeLogPropertyDefined property="myproperty" value="requiredvalue"/>

<customPrecondition>:可以通过创建实现liquibase.precondition的类来创建自定义前置条件。CustomPrecondition接口。自定义类的参数是通过基于子标记的反射设置的。参数作为字符串传递给自定义前置条件。

<customPrecondition className="com.example.CustomTableCheck">
    <param name="tableName" value="our_table"/>
    <param name="count" value="42"/>
</customPrecondition>

3.3 Properties标签 ​

为changelog定义一个参数。给定上下文 和/或 数据库的列表,该参数将仅在这些上下文 和/或 数据库中使用。

xml
<property name="clob.type" value="clob" dbms="oracle"/>
<property name="clob.type" value="longtext" dbms="mysql"/>

可用的配置项 ​

AttributeDescription
name表的数据库名称
value所需列的表的名称
context上下文,逗号分隔
dbms要用于该changeSet 的数据库的类型。关键字all和none也可用。
global定义属性是全局的还是局限于databaseChangeLog。“true”或“false”

数据库兼容配置 ​

xml
	<property name="autoIncrement" value="true" dbms="mysql" global="true"/>

    <!--clob类型-->
    <property name="clob.type" value="longtext" dbms="mysql"/>
    <property name="clob.type" value="clob" dbms="oracle, mssql, mariadb, postgresql"/>

    <!--int,还是不建议用,因为oracle和sql server 很难表示对应的4 294 967 295-->
    <property name="int_unsigned" value="int unsigned" dbms="mysql" global="true"/>
    <property name="int_unsigned" value="int" dbms="oracle, mssql" global="true"/>

    <!--tinyint可以直接用,但是mysql的数值范围是-128到127, oracle和sql server则是 0到255 -->
    <!--tinyint_unsigned-->
    <property name="tinyint_unsigned" value="tinyint unsigned" dbms="mysql" global="true"/>
    <property name="tinyint_unsigned" value="tinyint" dbms="mssql" global="true"/>
    <property name="tinyint_unsigned" value="Number(3, 0)" dbms="oracle" global="true"/>

    <!--boolean,没必要写boolean的兼容配置,想用的话直接用boolean就可以,liquibase会自动处理好-->
    <property name="boolean" value="tinyint" dbms="mysql" global="true"/>
    <property name="boolean" value="number(1, 0)" dbms="oracle" global="true"/>
    <property name="boolean" value="bit" dbms="mssql" global="true"/>

    <!-- Long整型存储 -->
    <property name="bigint" value="bigint" dbms="mysql" global="true"/>
    <property name="bigint" value="number(20,0)" dbms="oracle,mssql" global="true"/>

    <!-- Nvarchar兼容配置 -->
    <property name="nvarchar" value="varchar" dbms="mysql" global="true"/>
    <property name="nvarchar" value="nvarchar" dbms="oracle,mssql" global="true"/>

    <!--float-->
    <property name="floatType" value="float4" dbms="postgresql, h2"/>
    <property name="floatType" value="float" dbms="mysql, oracle, mssql, mariadb"/>

    <!-- 当前日期 -->
    <property name="now" value="now()" dbms="h2"/>
    <property name="now" value="now()" dbms="mysql"/>
    <property name="now" value="getutcdate()" dbms="mssql"/>
    <property name="now" value="sysdate" dbms="oracle"/>

    <property name="uuidType" value="varchar(36)" dbms="h2, mysql, mariadb"/>
    <property name="sequenceSchemaName" value="YHY" dbms="oracle, mssql"/>

3.4 changeSet标签 ​

主要由“id” 、“author”、changelog文件路径名组成

可用的属性值 ​

属性描述
id唯一识别,不一定是数字
author作者
dbms数据库类型
runAlways在每次运行时执行changeset ,即使之前已经运行过
runOnChange在第一次看到更改时执行更改,并且在每次changeset 时执行更改
context控制是否执行changeset,这取决于运行时设置。任何字符串都可以用于上下文名称,它们被不区分大小写地选中。
labels控制是否执行changeset,这取决于运行时设置。任何字符串都可以用于标签名称,并且不区分大小写地选中它们。
runInTransaction是否应该将changeset作为单个事务运行(如果可能的话)?默认值为true。
failOnError如果在执行changeset时发生错误,迁移是否应该失败
objectQuotingStrategy这控制了在生成的SQL中如何引用对象名,或者在对数据库的调用中如何使用对象名。不同的数据库对对象的名称执行不同的操作,例如Oracle将所有内容都转换为大写(除非使用引号)。有三个可能的值。默认值是LEGACY。三个配置的值: LEGACY - Same behavior as in Liquibase 2.0 QUOTE_ALL_OBJECTS - 每个对象都加上双引号 :person becomes “person”.QUOTE_ONLY_RESERVED_WORDS - 在保留关键字和可用列名上面加双引号

可用的子标签 ​

1)comment ​

注释

2)preConditions ​

前置条件,例如做一些不可逆操作前的必要检查

3)Any Refactoring Tag(s) ​

<Any Refactoring Tag(s)>要作为这个更改集的一部分运行的数据库更改

4)validCheckSum ​

添加一个校验和,不管数据库中存储了什么,它都被认为对这个changeset是有效的。主要用于需要更改changeset,并且不希望在已经运行了changeset的数据库上抛出错误(不推荐使用此过程)

5)rollback ​

描述如何回滚更改集的SQL语句或重构标记

rollback标签的示例:

xml
 <changeSet id="1" author="bob">
    <createTable tableName="testTable">
    <rollback>
        drop table testTable
    </rollback>
</changeSet>
<changeSet id="1" author="bob">
    <createTable tableName="testTable">
    <rollback>
        <dropTable tableName="testTable"/>
    </rollback>
</changeSet>
<changeSet id="2" author="bob">
    <dropTable tableName="testTable"/>
    <rollback changeSetId="1" changeSetAuthor="bob"/>
</changeSet>

这里发生了回滚,会调用id为1的changeSet 。

6)createIndex ​

【强制】主键索引名为pk字段名;唯一索引名为uk字段名;普通索引名则为idx字段名。 说明:pk 即primary key;uk_ 即 unique key;idx_ 即index的简称。

  • 普通索引名称以IDX为前缀。
  • 单字段索引的命名方式为:IDX表名字段名,表名无须前缀,命名长度太长时表名和字段名可以考虑缩写。
  • 多字段联合索引命名方式同单字段,考虑长度限制,可以只列出主要字段名或者采用缩写方式描述索引字段。 示例: \1. 错误命名:IDX_USER_INFO,没有给出字段名 \2. 错误命名:IDX_USER_INFO_DEPT_CODE,前缀错误。
xml
<changeSet id="20200509001" author="dongfang">
  <createIndex tableName="worker" indexName="idx_name">
    <column name="name"></column>
  </createIndex>
  <createIndex tableName="worker" indexName="idx_address_tel">
    <column name="address"></column>
    <column name="tel"></column>
  </createIndex>
</changeSet>
7)column ​

可以是单标签,也可以是双标签。双标签可以嵌套 <constraints /> 标签

8)addPrimaryKey ​
xml
  <addPrimaryKey columnNames="event_id, name" tableName="c_sys_persist_audit_evt_data"/>
9)addNotNullConstraint ​
xml
<addNotNullConstraint   columnName="password_hash" columnDataType="varchar(60)" tableName="c_usr_user"/>
10)addForeignKeyConstraint ​
xml
<addForeignKeyConstraint baseColumnNames="event_id" baseTableName="c_sys_persist_audit_evt_data" constraintName="fk_evt_pers_audit_evt_data" referencedColumnNames="event_id" referencedTableName="c_sys_persistent_audit_event"/>
11)dropDefaultValue ​
xml
<dropDefaultValue tableName="c_sys_common_menu" columnName="created_date" columnDataType="datetime"/>
12)loadData ​
xml
<loadData
          file="config/liquibase/project/user/fake-data/common_menu.csv"
          separator=";"
          tableName="c_sys_common_menu">
    <column name="id" type="numeric"/>
    <column name="created_by" type="string"/>
    <column name="created_date" type="datetime"/>
    <!-- jhipster-needle-liquibase-add-loadcolumn - JHipster (and/or extensions) can add load columns here, do not remove-->
</loadData>

3.5 include标签 ​

将change-logs拆分为易于管理的部分。

xml
<?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.8.xsd">
    <include file="com/example/news/news.changelog.xml"/>
    <include file="com/example/directory/directory.changelog.xml"/>
    
    <!--
    1:includeAll 标签可以把一个文件夹下的所有 changelog 都加载进来。如果单个加载可以用 include。
    2:includeAll 标签里有两个属性:path 和 relativeToChangelogFile。
        2.1:path (在 include 标签里是 file):指定要加载的文件或文件夹位置
        2.2:relativeToChangelogFile :文件位置的路径是否相对于 root changelog 是相对路径,默认 false,即相对于 classpath 是相对路径。
    -->
    <includeAll path="./sql/" relativeToChangelogFile="true"/>
</databaseChangeLog>

属性 ​

AttributeDescription
file被引入的文件
relativeToChangelogFile用文件的相对路径而不是classpath
context向所有包含的changeSets追加上下文(使用AND)

3.6 Contexts标签 ​

Liquibase 中的context是可以添加到changeSet 的标签,以控制将在任何特定的迁移运行中执行哪些设置。任何字符串都可用于上下文名称,并且它们处于不区分大小写状态。

通过任何可用方法运行迁移器时,可以传递一组要运行的context。将仅运行使用已传递上下文标记的changeset。在你迁移的时候如果没有指定一个具体的context,那么所有的context都会执行。

语法:context语法具体是使用AND,OR,!和圆括号。在没有圆括号的情况下,操作的顺序是!,AND,OR

context="!test"
context="v1.0 or map"
context="v1.0 or map"
context="!qa and !master"

使用 , 来分隔上下文的工作方式类似于 OR 操作,但具有最高的优先级。

"test,qa"`等价于`test OR qa`
`"test,qa and master"`等价于`test OR (qa AND master)

3.7 Rollback标签 ​

回滚标记描述如何对 SQL 语句、change tag或以前的changeSet的引用进行回滚更改。

多个语句可以被包含在一个<rollback>标签中。一个changeSet中可以有多个rollback标签

DATABASECHANGELOG表用于记录被执行过的changeset,当回滚后,就会删去被回滚掉的记录。

版本回滚 可以使用命令行 或者 maven ,ant 等构建工具来完成。

xml
<changeSet id="changeRollback" author="nvoxland">
    <createTable tableName="changeRollback1">
        <column name="id" type="int"/>
    </createTable>
    <rollback>
        <dropTable tableName="changeRollback1"/>
    </rollback>
</changeSet>

四、数据库版本控制 ​

4.1 更新版本 ​

sh
# 可在pom文件中指定版本标签,执行命令会自动进行更改


<NolebasePageProperties />




mvn clean package liquibase:update
# 也可命令行指定,还可以自己添加
mvn clean package liquibase:update -Dliquibase.tag=v3.0

4.2 添加版本标签 ​

每次版本升级,就打上一个标签,如V1.0、V2.0等,如果有问题,就回滚至对应标签(版本)

sh
# 命令行方式

mvn liquibase:tag -Dliquibase.tag=V1.1

4.3 maven配置方式 ​

在maven中配置后执行以上更新语句会自动添加标签

xml
<execution>                 
	<phase>process-resources</phase>
	<configuration>
		<!--版本指定,也可在命令执行时指定-->
		<tag>V1.1</tag>
	</configuration>
	<goals>
		<!--执行类型-->
		<goal>update</goal>
		<goal>tag</goal>
	</goals>
</execution>

4.4 版本回滚 ​

LiquiBase 提供了按数量、日期和标签回滚的能力,如下:

sh
# 按数量回滚,2表示回滚两个changeset
mvn liquibase:rollback -Dliquibase.rollbackCount=2
# 按日期回滚
mvn liquibase:rollback -Dliquibase.rollbackDate="2021-09-16 09:09:34"
# 按标签回滚
mvn liquibase:rollback -Dliquibase.rollbackTag=V1.0

4.5 生成回滚的sql脚本: ​

sh
mvn liquibase:rollbackSQL -Dliquibase.rollbackTag=v1.0

mvn liquibase:rollbackSQL -Dliquibase.rollbackDate="2021-09-16 09:09:34"

4.6 生成变更日志 ​

对于已有项目且之前未使用过Liquibase,使用 generateChangeLog 捕获数据库的当前状态,然后将这些更改应用于数据库。提供的扩展名决定了变更日志的格式,可为YAML或JSON或SQL或XML格式。

sh
mvn liquibase:generateChangeLog
-Dliquibase.outputChangeLogFile=changelog-test.xml

**注意:**如果生成 SQL 格式的更改日志,请将目标数据库的类型名称指定为文件名的一部分,如

changelog.<db_type>.sql

4.7 对比差异 ​

diff 允许您将相同类型或不同类型的两个数据库相互比较。

运行diff目标需要两个 URL:

referenceURL – 比较的来源。该referenceURL 属性代表您的源数据库。

URL – 比较的目标。该url 属性代表您要与源数据库进行比较的目标数据库。

sh
mvn liquibase:diff
-Dliquibase.changeLogFile=myChangeLog.xml
-Dliquibase.driver=oracle.jdbc.OracleDriver
-Dliquibase.url="jdbc:oracle:thin:@<IP OR HOSTNAME>:<PORT>:<SERVICE NAME OR SID>"
-Dliquibase.username=<USERNAME>
-Dliquibase.password=<PASSWORD>
-Dliquibase.referenceUrl="jdbc:oracle:thin:@<IP OR HOSTNAME>:<PORT>:<SERVICE NAME OR SID>"
-Dliquibase.referenceUsername=<USERNAME>
-Dliquibase.referencePassword=<PASSWORD>

生成将源数据库与目标数据库进行比较后应用更改的更改日志

生成将源数据库与目标数据库进行比较后应用更改的更改日志

sh
mvn liquibase:diff -Dliquibase.diffChangeLogFile=mydiff.xml

Liquibase允许您使用diffTypes 属性来过滤要比较的对象类型。可以将多个过滤器作为逗号分隔列表添加到属性中。如果没有diffTypes指定,则考虑所有对象。

sh
mvn liquibase:diff -Dliquibase.diffTypes=tables,indexes,views

更多maven命令可查看:https://docs.liquibase.com/tools-integrations/maven/commands/home.html

五、liquibase 命令附录 ​

更多命令可查看官方文档:https://docsstage.liquibase.com/commands/home.html

命令名称命令描述
update更新数据库到当前版本
updateSQL写入SQL将数据库更新到currentversion或STDOUT
updateCount将本地num个未执行的changeset更改应用到数据库
updateCountSQL将本地num个未执行的changeset输出到sql文件
updateToTag更新数据库到指定tag的changeset
updateToTagSQL更新数据库到指定tag的changeset输出到sql文件
rollback将数据库回滚到指定标签的状态
rollbackSQL将数据库回滚到指定标签的状态的sql
rollbackToDate <date/time>将数据库回滚到给定日期/时间的状态。日期格式为YYYY-MM-DD HH:MM:SS或YYYY-MM-DD'T'HH:MM:SS,但可以仅指示日期或时间。
rollbackToDateSQL <date/time>写入SQL以将数据库回滚到给定日期/时间版本的状态到STDOUT
rollbackCount回滚最近num个changeset
rollbackCountSQL回滚最近num个changeset输出到sql
futureRollbackSQL执行rollback标签里边的sql
futureRollbackSQL输出rollback里边的sql到sql文件
futureRollbackFromTagSQL输出指定tag的回滚sql
updateTestingRollback回滚更新数据库,然后再次回滚更改。用于测试回滚支持
generateChangeLog写入更改日志XML以将数据库的当前状态复制到标准输出
snapshot将数据库的当前状态写入标准输出
snapshotReference将referenceUrl数据库的当前状态写入标准输出
Diff Commands数据库对比命令
diff [diff parameters]数据库对比命令
diffChangeLog [diff parameters]数据库对比日志
Documentation Commands生成文档命令
dbDoc基于当前数据库和更改日志生成类似javadoc的文档
Maintenance Commands维护命令
tag给当前的数据库打标签,(只会打最新的一条记录的tag)
tagExists检查对应的标签是否存在
status [–verbose]输出为执行changeset的行数
unexpectedChangeSets[–verbose]输出本地不存在changeset 行数
validate检查是否有错误的changelog
calculateCheckSum检查指定changeset id 的checksum值 格式为 filepath:🆔:author
clearCheckSums从数据库日志中删除所有保存的校验和
changelogSync标记所有的更改已执行
changelogSyncSQL生成标记更改已执行的sql并输出到标准输出
markNextChangeSetRan将下一个变更标记为已执行
markNextChangeSetRanSQL生成将下一个变更标记为已执行的sql并输出到标准输出
listLocks列出liquibase数据库锁
releaseLocks释放所有的liquibase数据库锁
dropAll删除数据库表(慎用!)

六、完整数据列表 ​

6.1 boolean ​

数据库类型
MySQLBIT(1)
MSSQLbit
OracleNUMBER(1)
SQLiteBOOLEAN
H2BOOLEAN
PostgresDatabaseBOOLEAN
UnsupportedBOOLEAN
DB2SMALLINT
HsqlBOOLEAN
FirebirdDatabaseSMALLINT
DerbyDatabaseSMALLINT
InformixDatabaseBOOLEAN
SybaseDatabaseBIT
SybaseASADatabaseBIT

6.2 tinyint ​

数据库类型
MySQLTINYINT
MSSQLTINYINT
OracleNUMBER(3)
SQLiteTINYINT
H2TINYINT
PostgresDatabaseSMALLINT
UnsupportedTINYINT
DB2SMALLINT
HsqlTINYINT
FirebirdDatabaseSMALLINT
DerbyDatabaseSMALLINT
InformixDatabaseTINYINT
SybaseDatabaseTINYINT
SybaseASADatabaseTINYINT

6.3 int ​

数据库类型
MySQLint
MSSQLint
OracleINTEGER
SQLiteINTEGER
H2int
PostgresDatabaseint
Unsupportedint
DB2INTEGER
Hsqlint
FirebirdDatabaseint
DerbyDatabaseINTEGER
InformixDatabaseint
SybaseDatabaseint
SybaseASADatabaseint

6.4 mediumint ​

数据库类型
MySQLMEDIUMINT
MSSQLint
OracleMEDIUMINT
SQLiteMEDIUMINT
H2MEDIUMINT
PostgresDatabaseMEDIUMINT
UnsupportedMEDIUMINT
DB2MEDIUMINT
HsqlMEDIUMINT
FirebirdDatabaseMEDIUMINT
DerbyDatabaseMEDIUMINT
InformixDatabaseMEDIUMINT
SybaseDatabaseMEDIUMINT
SybaseASADatabaseMEDIUMINT

6.5 bigint ​

数据库类型
MySQLBIGINT
MSSQLBIGINT
OracleNUMBER(38,0)
SQLiteBIGINT
H2BIGINT
PostgresDatabaseBIGINT
UnsupportedBIGINT
DB2BIGINT
HsqlBIGINT
FirebirdDatabaseBIGINT
DerbyDatabaseBIGINT
InformixDatabaseINT8
SybaseDatabaseBIGINT
SybaseASADatabaseBIGINT

6.6 float ​

数据库类型
MySQLFLOAT
MSSQLFLOAT
OracleFLOAT
SQLiteFLOAT
H2FLOAT
PostgresDatabaseFLOAT
UnsupportedFLOAT
DB2FLOAT
HsqlFLOAT
FirebirdDatabaseFLOAT
DerbyDatabaseFLOAT
InformixDatabaseFLOAT
SybaseDatabaseFLOAT
SybaseASADatabaseFLOAT

6.7 double ​

数据库类型
MySQLDOUBLE
MSSQL[float](53)
OracleFLOAT(24)
SQLiteDOUBLE
H2DOUBLE
PostgresDatabaseDOUBLE
UnsupportedDOUBLE
DB2DOUBLE
HsqlDOUBLE
FirebirdDatabaseDOUBLE PRECISION
DerbyDatabaseDOUBLE
InformixDatabaseDOUBLE PRECISION
SybaseDatabaseDOUBLE
SybaseASADatabaseDOUBLE

6.8 decimal ​

数据库类型
MySQLDECIMAL
MSSQL[decimal](18,0)
OracleDECIMAL
SQLiteDECIMAL
H2DECIMAL
PostgresDatabaseDECIMAL
UnsupportedDECIMAL
DB2DECIMAL
HsqlDECIMAL
FirebirdDatabaseDECIMAL
DerbyDatabaseDECIMAL
InformixDatabaseDECIMAL
SybaseDatabaseDECIMAL
SybaseASADatabaseDECIMAL

6.9 number ​

数据库类型
MySQLnumeric,经测试会是decimal(10, 0)
MSSQL[numeric](18,0)
OracleNUMBER
SQLiteNUMBER
H2NUMBER
PostgresDatabasenumeric
UnsupportedNUMBER
DB2numeric
Hsqlnumeric
FirebirdDatabasenumeric
DerbyDatabasenumeric
InformixDatabasenumeric
SybaseDatabasenumeric
SybaseASADatabasenumeric

6.10 blob ​

数据库类型
MySQLLONGBLOB,经测试是blob
MSSQL[varbinary](MAX)
OracleBLOB
SQLiteBLOB
H2BLOB
PostgresDatabaseBYTEA
UnsupportedBLOB
DB2BLOB
HsqlBLOB
FirebirdDatabaseBLOB
DerbyDatabaseBLOB
InformixDatabaseBLOB
SybaseDatabaseIMAGE
SybaseASADatabaseLONG BINARY

6.11 clob ​

数据库类型
MySQLLONGTEXT
MSSQL[varchar](MAX)
OracleCLOB
SQLiteTEXT
H2CLOB
PostgresDatabaseTEXT
UnsupportedCLOB
DB2CLOB
HsqlCLOB
FirebirdDatabaseBLOB
DerbyDatabaseCLOB
InformixDatabaseCLOB
SybaseDatabaseTEXT
SybaseASADatabaseLONG VARCHAR

6.12 function ​

数据库类型
MySQLFUNCTION
MSSQL[function]
OracleFUNCTION
SQLiteFUNCTION
H2FUNCTION
PostgresDatabaseFUNCTION
UnsupportedFUNCTION
DB2FUNCTION
HsqlFUNCTION
FirebirdDatabaseFUNCTION
DerbyDatabaseFUNCTION
InformixDatabaseFUNCTION
SybaseDatabaseFUNCTION
SybaseASADatabaseFUNCTION

6.13 UNKNOWN ​

数据库类型
MySQLUNKNOWN
MSSQL[UNKNOWN]
OracleUNKNOWN
SQLiteUNKNOWN
H2UNKNOWN
PostgresDatabaseUNKNOWN
UnsupportedUNKNOWN
DB2UNKNOWN
HsqlUNKNOWN
FirebirdDatabaseUNKNOWN
DerbyDatabaseUNKNOWN
InformixDatabaseUNKNOWN
SybaseDatabaseUNKNOWN
SybaseASADatabaseUNKNOWN

6.14 datetime ​

数据库类型
MySQLdatetime
MSSQL[datetime]
OracleTIMESTAMP
SQLiteTEXT
H2TIMESTAMP
PostgresDatabaseTIMESTAMP WITHOUT TIME ZONE
Unsupporteddatetime
DB2TIMESTAMP
HsqlTIMESTAMP
FirebirdDatabaseTIMESTAMP
DerbyDatabaseTIMESTAMP
InformixDatabaseDATETIME年份分数(5)
SybaseDatabasedatetime
SybaseASADatabasedatetime

6.15 time ​

数据库类型
MySQLtime
MSSQL[time](7)
OracleDATE
SQLitetime
H2time
PostgresDatabaseTIME WITHOUT TIME ZONE
Unsupportedtime
DB2time
Hsqltime
FirebirdDatabasetime
DerbyDatabasetime
InformixDatabaseINTERVAL HOUR TO FRACTION(5)
SybaseDatabasetime
SybaseASADatabasetime

6.16 timestamp ​

数据库类型
MySQLtimestamp
MSSQL[datetime]
OracleTIMESTAMP
SQLiteTEXT
H2TIMESTAMP
PostgresDatabaseTIMESTAMP WITHOUT TIME ZONE
Unsupportedtimestamp
DB2timestamp
HsqlTIMESTAMP
FirebirdDatabaseTIMESTAMP
DerbyDatabaseTIMESTAMP
InformixDatabaseDATETIME年份分数(5)
SybaseDatabasedatetime
SybaseASADatabasetimestamp

6.17 date ​

数据库类型
MySQLdate
MSSQL[date]
Oracledate
SQLitedate
H2date
PostgresDatabasedate
Unsupporteddate
DB2date
Hsqldate
FirebirdDatabasedate
DerbyDatabasedate
InformixDatabasedate
SybaseDatabasedate
SybaseASADatabasedate

6.18 char ​

数据库类型
MySQLCHAR
MSSQL[char](1)
OracleCHAR
SQLiteCHAR
H2CHAR
PostgresDatabaseCHAR
UnsupportedCHAR
DB2CHAR
HsqlCHAR
FirebirdDatabaseCHAR
DerbyDatabaseCHAR
InformixDatabaseCHAR
SybaseDatabaseCHAR
SybaseASADatabaseCHAR

6.19 varchar ​

数据库类型
MySQLVARCHAR
MSSQL[varchar](1)
OracleVARCHAR2
SQLiteVARCHAR
H2VARCHAR
PostgresDatabaseVARCHAR
UnsupportedVARCHAR
DB2VARCHAR
HsqlVARCHAR
FirebirdDatabaseVARCHAR
DerbyDatabaseVARCHAR
InformixDatabaseVARCHAR
SybaseDatabaseVARCHAR
SybaseASADatabaseVARCHAR

6.20 nchar ​

数据库类型
MySQLNCHAR
MSSQL[nchar](1)
OracleNCHAR
SQLiteNCHAR
H2NCHAR
PostgresDatabaseNCHAR
UnsupportedNCHAR
DB2NCHAR
HsqlNCHAR
FirebirdDatabaseNCHAR
DerbyDatabaseNCHAR
InformixDatabaseNCHAR
SybaseDatabaseNCHAR
SybaseASADatabaseNCHAR

6.21 nvarchar ​

数据库类型
MySQLNVARCHAR,经测试,mysql还是用的varchar,但是mysql的varchar就相当于nvarchar
MSSQL[nvarchar](1)
OracleNVARCHAR2
SQLiteNVARCHAR
H2NVARCHAR
PostgresDatabaseNVARCHAR
UnsupportedNVARCHAR
DB2NVARCHAR
HsqlVARCHAR
FirebirdDatabaseNVARCHAR
DerbyDatabaseVARCHAR
InformixDatabaseNVARCHAR
SybaseDatabaseNVARCHAR
SybaseASADatabaseNVARCHAR

6.22 currency ​

数据库类型
MySQLDECIMAL
MSSQL[money]
OracleNUMBER(15,2)
SQLiteREAL
H2DECIMAL
PostgresDatabaseDECIMAL
UnsupportedDECIMAL
DB2DECIMAL(19,4)
HsqlDECIMAL
FirebirdDatabaseDECIMAL(18,4)
DerbyDatabaseDECIMAL
InformixDatabaseMONEY
SybaseDatabaseMONEY
SybaseASADatabaseMONEY

6.23 uuid ​

数据库类型
MySQLchar(36)
MSSQL[uniqueidentifier]
OracleRAW(16)
SQLiteTEXT
H2UUID
PostgresDatabaseUUID
Unsupportedchar(36)
DB2char(36)
Hsqlchar(36)
FirebirdDatabasechar(36)
DerbyDatabasechar(36)
InformixDatabasechar(36)
SybaseDatabaseUNIQUEIDENTIFIER
SybaseASADatabaseUNIQUEIDENTIFIER