一、概述
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集成
依赖
<!--Liquibase-->
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>配置
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 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 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>子标签
| tag | Description |
|---|---|
| preConditions | 执行sql变更文件的前置条件 |
| property | 设置的属性的值 |
| changeSet | 要执行的更改 |
| include | 包含要执行的更改集的附加文件 |
| context | 上下文将被附加到(使用AND)所有变更集 |
3.2 preConditions标签
可以应用于<databaseChangeLog>标签或者<changeSet>标签。
先决条件可以应用于整个changelog或单个changeSet。如果先决条件失败,liquibase将停止执行。
<?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的命令将不会执行。
处理失败和错误
| Attribute | Description |
|---|---|
| onFail | 当preConditions是失败情形下如何处理 |
| OnError | 当preConditions是错误情形下如何处理 |
| onSqlOutput | 在updateSQL模式下要做什么 |
| onFailMessage | 输出的失败信息 |
| onErrorMessage | 输出的错误信息 |
OnFail/OnError值可能配置的值
| Value | Description |
|---|---|
| HALT | 立即停止执行整个更改日志。 [默认] |
| CONTINUE | 跳过* changeSet 。 下次更新时将再次尝试执行更改集。 继续 changelog * |
| MARK_RAN | 跳过更改集,但将其标记为已执行。继续更改日志。 |
| WARN | 输出警告并继续照常执行* changeSet * / * changelog *。 |
onSqlOutput可能配置的值
| Value | Description |
|---|---|
| TEST | 在updateSQL模式下运行changeSet |
| FAIL | 使preConditons在updateSQL模式下失败 |
| IGNORE | 忽略updateSQL模式中的preConditons(默认)。 |
and/or/not逻辑
使用nestable <and>、<or>和<not>标记将条件逻辑应用于前置条件。如果没有指定条件标记,则默认为AND。
复合条件,例如,是oracle数据库,并且用户必须是SYSTEM 或者 数据库是mysql,且用户需要为root时
<preConditions>
<or>
<and>
<dbms type="oracle" />
<runningAs username="SYSTEM" />
</and>
<and>
<dbms type="mysql" />
<runningAs username="root" />
</and>
</or>
</preConditions>可用的preConditions子标签
<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定义一个参数。给定上下文 和/或 数据库的列表,该参数将仅在这些上下文 和/或 数据库中使用。
<property name="clob.type" value="clob" dbms="oracle"/>
<property name="clob.type" value="longtext" dbms="mysql"/>可用的配置项
| Attribute | Description |
|---|---|
| name | 表的数据库名称 |
| value | 所需列的表的名称 |
| context | 上下文,逗号分隔 |
| dbms | 要用于该changeSet 的数据库的类型。关键字all和none也可用。 |
| global | 定义属性是全局的还是局限于databaseChangeLog。“true”或“false” |
数据库兼容配置
<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标签的示例:
<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,前缀错误。
<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
<addPrimaryKey columnNames="event_id, name" tableName="c_sys_persist_audit_evt_data"/>9)addNotNullConstraint
<addNotNullConstraint columnName="password_hash" columnDataType="varchar(60)" tableName="c_usr_user"/>10)addForeignKeyConstraint
<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
<dropDefaultValue tableName="c_sys_common_menu" columnName="created_date" columnDataType="datetime"/>12)loadData
<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 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>属性
| Attribute | Description |
|---|---|
| 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 等构建工具来完成。
<changeSet id="changeRollback" author="nvoxland">
<createTable tableName="changeRollback1">
<column name="id" type="int"/>
</createTable>
<rollback>
<dropTable tableName="changeRollback1"/>
</rollback>
</changeSet>四、数据库版本控制
4.1 更新版本
# 可在pom文件中指定版本标签,执行命令会自动进行更改
<NolebasePageProperties />
mvn clean package liquibase:update
# 也可命令行指定,还可以自己添加
mvn clean package liquibase:update -Dliquibase.tag=v3.04.2 添加版本标签
每次版本升级,就打上一个标签,如V1.0、V2.0等,如果有问题,就回滚至对应标签(版本)
# 命令行方式
mvn liquibase:tag -Dliquibase.tag=V1.14.3 maven配置方式
在maven中配置后执行以上更新语句会自动添加标签
<execution>
<phase>process-resources</phase>
<configuration>
<!--版本指定,也可在命令执行时指定-->
<tag>V1.1</tag>
</configuration>
<goals>
<!--执行类型-->
<goal>update</goal>
<goal>tag</goal>
</goals>
</execution>4.4 版本回滚
LiquiBase 提供了按数量、日期和标签回滚的能力,如下:
# 按数量回滚,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.04.5 生成回滚的sql脚本:
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格式。
mvn liquibase:generateChangeLog
-Dliquibase.outputChangeLogFile=changelog-test.xml**注意:**如果生成 SQL 格式的更改日志,请将目标数据库的类型名称指定为文件名的一部分,如
changelog.<db_type>.sql
4.7 对比差异
diff 允许您将相同类型或不同类型的两个数据库相互比较。
运行diff目标需要两个 URL:
referenceURL – 比较的来源。该referenceURL 属性代表您的源数据库。
URL – 比较的目标。该url 属性代表您要与源数据库进行比较的目标数据库。
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>生成将源数据库与目标数据库进行比较后应用更改的更改日志
生成将源数据库与目标数据库进行比较后应用更改的更改日志
mvn liquibase:diff -Dliquibase.diffChangeLogFile=mydiff.xmlLiquibase允许您使用diffTypes 属性来过滤要比较的对象类型。可以将多个过滤器作为逗号分隔列表添加到属性中。如果没有diffTypes指定,则考虑所有对象。
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
| 数据库 | 类型 |
|---|---|
| MySQL | BIT(1) |
| MSSQL | bit |
| Oracle | NUMBER(1) |
| SQLite | BOOLEAN |
| H2 | BOOLEAN |
| PostgresDatabase | BOOLEAN |
| Unsupported | BOOLEAN |
| DB2 | SMALLINT |
| Hsql | BOOLEAN |
| FirebirdDatabase | SMALLINT |
| DerbyDatabase | SMALLINT |
| InformixDatabase | BOOLEAN |
| SybaseDatabase | BIT |
| SybaseASADatabase | BIT |
6.2 tinyint
| 数据库 | 类型 |
|---|---|
| MySQL | TINYINT |
| MSSQL | TINYINT |
| Oracle | NUMBER(3) |
| SQLite | TINYINT |
| H2 | TINYINT |
| PostgresDatabase | SMALLINT |
| Unsupported | TINYINT |
| DB2 | SMALLINT |
| Hsql | TINYINT |
| FirebirdDatabase | SMALLINT |
| DerbyDatabase | SMALLINT |
| InformixDatabase | TINYINT |
| SybaseDatabase | TINYINT |
| SybaseASADatabase | TINYINT |
6.3 int
| 数据库 | 类型 |
|---|---|
| MySQL | int |
| MSSQL | int |
| Oracle | INTEGER |
| SQLite | INTEGER |
| H2 | int |
| PostgresDatabase | int |
| Unsupported | int |
| DB2 | INTEGER |
| Hsql | int |
| FirebirdDatabase | int |
| DerbyDatabase | INTEGER |
| InformixDatabase | int |
| SybaseDatabase | int |
| SybaseASADatabase | int |
6.4 mediumint
| 数据库 | 类型 |
|---|---|
| MySQL | MEDIUMINT |
| MSSQL | int |
| Oracle | MEDIUMINT |
| SQLite | MEDIUMINT |
| H2 | MEDIUMINT |
| PostgresDatabase | MEDIUMINT |
| Unsupported | MEDIUMINT |
| DB2 | MEDIUMINT |
| Hsql | MEDIUMINT |
| FirebirdDatabase | MEDIUMINT |
| DerbyDatabase | MEDIUMINT |
| InformixDatabase | MEDIUMINT |
| SybaseDatabase | MEDIUMINT |
| SybaseASADatabase | MEDIUMINT |
6.5 bigint
| 数据库 | 类型 |
|---|---|
| MySQL | BIGINT |
| MSSQL | BIGINT |
| Oracle | NUMBER(38,0) |
| SQLite | BIGINT |
| H2 | BIGINT |
| PostgresDatabase | BIGINT |
| Unsupported | BIGINT |
| DB2 | BIGINT |
| Hsql | BIGINT |
| FirebirdDatabase | BIGINT |
| DerbyDatabase | BIGINT |
| InformixDatabase | INT8 |
| SybaseDatabase | BIGINT |
| SybaseASADatabase | BIGINT |
6.6 float
| 数据库 | 类型 |
|---|---|
| MySQL | FLOAT |
| MSSQL | FLOAT |
| Oracle | FLOAT |
| SQLite | FLOAT |
| H2 | FLOAT |
| PostgresDatabase | FLOAT |
| Unsupported | FLOAT |
| DB2 | FLOAT |
| Hsql | FLOAT |
| FirebirdDatabase | FLOAT |
| DerbyDatabase | FLOAT |
| InformixDatabase | FLOAT |
| SybaseDatabase | FLOAT |
| SybaseASADatabase | FLOAT |
6.7 double
| 数据库 | 类型 |
|---|---|
| MySQL | DOUBLE |
| MSSQL | [float](53) |
| Oracle | FLOAT(24) |
| SQLite | DOUBLE |
| H2 | DOUBLE |
| PostgresDatabase | DOUBLE |
| Unsupported | DOUBLE |
| DB2 | DOUBLE |
| Hsql | DOUBLE |
| FirebirdDatabase | DOUBLE PRECISION |
| DerbyDatabase | DOUBLE |
| InformixDatabase | DOUBLE PRECISION |
| SybaseDatabase | DOUBLE |
| SybaseASADatabase | DOUBLE |
6.8 decimal
| 数据库 | 类型 |
|---|---|
| MySQL | DECIMAL |
| MSSQL | [decimal](18,0) |
| Oracle | DECIMAL |
| SQLite | DECIMAL |
| H2 | DECIMAL |
| PostgresDatabase | DECIMAL |
| Unsupported | DECIMAL |
| DB2 | DECIMAL |
| Hsql | DECIMAL |
| FirebirdDatabase | DECIMAL |
| DerbyDatabase | DECIMAL |
| InformixDatabase | DECIMAL |
| SybaseDatabase | DECIMAL |
| SybaseASADatabase | DECIMAL |
6.9 number
| 数据库 | 类型 |
|---|---|
| MySQL | numeric,经测试会是decimal(10, 0) |
| MSSQL | [numeric](18,0) |
| Oracle | NUMBER |
| SQLite | NUMBER |
| H2 | NUMBER |
| PostgresDatabase | numeric |
| Unsupported | NUMBER |
| DB2 | numeric |
| Hsql | numeric |
| FirebirdDatabase | numeric |
| DerbyDatabase | numeric |
| InformixDatabase | numeric |
| SybaseDatabase | numeric |
| SybaseASADatabase | numeric |
6.10 blob
| 数据库 | 类型 |
|---|---|
| MySQL | LONGBLOB,经测试是blob |
| MSSQL | [varbinary](MAX) |
| Oracle | BLOB |
| SQLite | BLOB |
| H2 | BLOB |
| PostgresDatabase | BYTEA |
| Unsupported | BLOB |
| DB2 | BLOB |
| Hsql | BLOB |
| FirebirdDatabase | BLOB |
| DerbyDatabase | BLOB |
| InformixDatabase | BLOB |
| SybaseDatabase | IMAGE |
| SybaseASADatabase | LONG BINARY |
6.11 clob
| 数据库 | 类型 |
|---|---|
| MySQL | LONGTEXT |
| MSSQL | [varchar](MAX) |
| Oracle | CLOB |
| SQLite | TEXT |
| H2 | CLOB |
| PostgresDatabase | TEXT |
| Unsupported | CLOB |
| DB2 | CLOB |
| Hsql | CLOB |
| FirebirdDatabase | BLOB |
| DerbyDatabase | CLOB |
| InformixDatabase | CLOB |
| SybaseDatabase | TEXT |
| SybaseASADatabase | LONG VARCHAR |
6.12 function
| 数据库 | 类型 |
|---|---|
| MySQL | FUNCTION |
| MSSQL | [function] |
| Oracle | FUNCTION |
| SQLite | FUNCTION |
| H2 | FUNCTION |
| PostgresDatabase | FUNCTION |
| Unsupported | FUNCTION |
| DB2 | FUNCTION |
| Hsql | FUNCTION |
| FirebirdDatabase | FUNCTION |
| DerbyDatabase | FUNCTION |
| InformixDatabase | FUNCTION |
| SybaseDatabase | FUNCTION |
| SybaseASADatabase | FUNCTION |
6.13 UNKNOWN
| 数据库 | 类型 |
|---|---|
| MySQL | UNKNOWN |
| MSSQL | [UNKNOWN] |
| Oracle | UNKNOWN |
| SQLite | UNKNOWN |
| H2 | UNKNOWN |
| PostgresDatabase | UNKNOWN |
| Unsupported | UNKNOWN |
| DB2 | UNKNOWN |
| Hsql | UNKNOWN |
| FirebirdDatabase | UNKNOWN |
| DerbyDatabase | UNKNOWN |
| InformixDatabase | UNKNOWN |
| SybaseDatabase | UNKNOWN |
| SybaseASADatabase | UNKNOWN |
6.14 datetime
| 数据库 | 类型 |
|---|---|
| MySQL | datetime |
| MSSQL | [datetime] |
| Oracle | TIMESTAMP |
| SQLite | TEXT |
| H2 | TIMESTAMP |
| PostgresDatabase | TIMESTAMP WITHOUT TIME ZONE |
| Unsupported | datetime |
| DB2 | TIMESTAMP |
| Hsql | TIMESTAMP |
| FirebirdDatabase | TIMESTAMP |
| DerbyDatabase | TIMESTAMP |
| InformixDatabase | DATETIME年份分数(5) |
| SybaseDatabase | datetime |
| SybaseASADatabase | datetime |
6.15 time
| 数据库 | 类型 |
|---|---|
| MySQL | time |
| MSSQL | [time](7) |
| Oracle | DATE |
| SQLite | time |
| H2 | time |
| PostgresDatabase | TIME WITHOUT TIME ZONE |
| Unsupported | time |
| DB2 | time |
| Hsql | time |
| FirebirdDatabase | time |
| DerbyDatabase | time |
| InformixDatabase | INTERVAL HOUR TO FRACTION(5) |
| SybaseDatabase | time |
| SybaseASADatabase | time |
6.16 timestamp
| 数据库 | 类型 |
|---|---|
| MySQL | timestamp |
| MSSQL | [datetime] |
| Oracle | TIMESTAMP |
| SQLite | TEXT |
| H2 | TIMESTAMP |
| PostgresDatabase | TIMESTAMP WITHOUT TIME ZONE |
| Unsupported | timestamp |
| DB2 | timestamp |
| Hsql | TIMESTAMP |
| FirebirdDatabase | TIMESTAMP |
| DerbyDatabase | TIMESTAMP |
| InformixDatabase | DATETIME年份分数(5) |
| SybaseDatabase | datetime |
| SybaseASADatabase | timestamp |
6.17 date
| 数据库 | 类型 |
|---|---|
| MySQL | date |
| MSSQL | [date] |
| Oracle | date |
| SQLite | date |
| H2 | date |
| PostgresDatabase | date |
| Unsupported | date |
| DB2 | date |
| Hsql | date |
| FirebirdDatabase | date |
| DerbyDatabase | date |
| InformixDatabase | date |
| SybaseDatabase | date |
| SybaseASADatabase | date |
6.18 char
| 数据库 | 类型 |
|---|---|
| MySQL | CHAR |
| MSSQL | [char](1) |
| Oracle | CHAR |
| SQLite | CHAR |
| H2 | CHAR |
| PostgresDatabase | CHAR |
| Unsupported | CHAR |
| DB2 | CHAR |
| Hsql | CHAR |
| FirebirdDatabase | CHAR |
| DerbyDatabase | CHAR |
| InformixDatabase | CHAR |
| SybaseDatabase | CHAR |
| SybaseASADatabase | CHAR |
6.19 varchar
| 数据库 | 类型 |
|---|---|
| MySQL | VARCHAR |
| MSSQL | [varchar](1) |
| Oracle | VARCHAR2 |
| SQLite | VARCHAR |
| H2 | VARCHAR |
| PostgresDatabase | VARCHAR |
| Unsupported | VARCHAR |
| DB2 | VARCHAR |
| Hsql | VARCHAR |
| FirebirdDatabase | VARCHAR |
| DerbyDatabase | VARCHAR |
| InformixDatabase | VARCHAR |
| SybaseDatabase | VARCHAR |
| SybaseASADatabase | VARCHAR |
6.20 nchar
| 数据库 | 类型 |
|---|---|
| MySQL | NCHAR |
| MSSQL | [nchar](1) |
| Oracle | NCHAR |
| SQLite | NCHAR |
| H2 | NCHAR |
| PostgresDatabase | NCHAR |
| Unsupported | NCHAR |
| DB2 | NCHAR |
| Hsql | NCHAR |
| FirebirdDatabase | NCHAR |
| DerbyDatabase | NCHAR |
| InformixDatabase | NCHAR |
| SybaseDatabase | NCHAR |
| SybaseASADatabase | NCHAR |
6.21 nvarchar
| 数据库 | 类型 |
|---|---|
| MySQL | NVARCHAR,经测试,mysql还是用的varchar,但是mysql的varchar就相当于nvarchar |
| MSSQL | [nvarchar](1) |
| Oracle | NVARCHAR2 |
| SQLite | NVARCHAR |
| H2 | NVARCHAR |
| PostgresDatabase | NVARCHAR |
| Unsupported | NVARCHAR |
| DB2 | NVARCHAR |
| Hsql | VARCHAR |
| FirebirdDatabase | NVARCHAR |
| DerbyDatabase | VARCHAR |
| InformixDatabase | NVARCHAR |
| SybaseDatabase | NVARCHAR |
| SybaseASADatabase | NVARCHAR |
6.22 currency
| 数据库 | 类型 |
|---|---|
| MySQL | DECIMAL |
| MSSQL | [money] |
| Oracle | NUMBER(15,2) |
| SQLite | REAL |
| H2 | DECIMAL |
| PostgresDatabase | DECIMAL |
| Unsupported | DECIMAL |
| DB2 | DECIMAL(19,4) |
| Hsql | DECIMAL |
| FirebirdDatabase | DECIMAL(18,4) |
| DerbyDatabase | DECIMAL |
| InformixDatabase | MONEY |
| SybaseDatabase | MONEY |
| SybaseASADatabase | MONEY |
6.23 uuid
| 数据库 | 类型 |
|---|---|
| MySQL | char(36) |
| MSSQL | [uniqueidentifier] |
| Oracle | RAW(16) |
| SQLite | TEXT |
| H2 | UUID |
| PostgresDatabase | UUID |
| Unsupported | char(36) |
| DB2 | char(36) |
| Hsql | char(36) |
| FirebirdDatabase | char(36) |
| DerbyDatabase | char(36) |
| InformixDatabase | char(36) |
| SybaseDatabase | UNIQUEIDENTIFIER |
| SybaseASADatabase | UNIQUEIDENTIFIER |