Liquibase基础实践
一、What liquibase
LiquiBase 是一个用于数据库重构和迁移的开源工具,通过日志文件的形式记录数据库的变更,然后执行日志文件中的修改,将数据库更新或回滚到一致的状态。可以理解为数据库管理工具类似git。
二、Why liquibase
- 支持几乎所有主流的数据库,如MySQL, PostgreSQL, Oracle, Sql Server, DB2等;
- 支持多开发者的协作维护;
- 日志文件支持多种格式,如XML, YAML, JSON, SQL等;
- 支持多种运行方式,如命令行、Spring集成、Maven插件、Gradle插件等;
三、How liquibase
liquibase官网的quick start:
- Create a Changelog File
changelog是LiquiBase用来记录数据库的变更,一般放在CLASSPATH下,然后配置到执行路径中。
changelog支持多种格式,主要有XML/JSON/YAML/SQL,其中XML/JSON/YAML除了具体格式语法不同,节点配置很类似,SQL格式中主要记录SQL语句,这里仅给出XML格式,更多的格式示例请参考文档
<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"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
</databaseChangeLog>
官方文档还给出了databaseChangeLog里可用的子标签:
标签 | 描述 |
---|---|
preConditions | 执行changeLog需的前提条件。阅读更多 |
property | 设置属性的值。阅读更多 |
changeSet | 需执行的更改。阅读更多 |
include | 包含要执行的更改集的其他文件。阅读更多 |
- Add a ChangeSet
添加ChangeSet
<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.6.xsd">
<!-- 使用liquibase的语法 -->
<changeSet id="createStudentInfo" author="jmn">
<createTable tableName="student_info">
<column autoIncrement="true" name="id" remarks="主键ID" type="BIGSERIAL"/>
<column name="student_name" remarks="学生姓名" type="VARCHAR(16)"/>
<column name="sex" remarks="性别" type="SMALLINT"/>
<column name="age" remarks="年龄" type="VARCHAR(10)"/>
<column name="grade" remarks="成绩" type="INTEGER"/>
</createTable>
</changeSet>
<!-- 引入sql文件方式 -->
<changeSet id="createUserInfo" author="jmn">
<sqlFile path="../sql/user_info.sql" relativeToChangelogFile="true"/>
</changeSet>
</databaseChangeLog>
- Run the ChangeSet
有许多方法可以执行changeLog,包括通过命令行,Ant,Maven,Spring等
liquibase --driver=com.mysql.jdbc.Driver \
--classpath=/path/to/classes \
--changeLogFile=com/example/db.changelog.xml \
--url="jdbc:mysql://localhost/example" \
--username=user \
--password=asdf \
update
- Check Your Database
你将看到你的数据库现在包含两个名为“student_info”,“user_info”的表。还创建了另外两个表:“databasechangelog” 和 “databasechangeloglock”。
databasechangelog表包含已针对数据库运行的所有语句的列表。
databasechangeloglock表用于确保两台计算机不会同时尝试修改数据库。
四、springboot + liquibase
- application.yml配置文件中增加liquibase配置
liquibase:
#是否开启liquibase
#spring boot 2以上:spring.liquibase.enabled=false
#spring boot 2以下:liquibase.enabled=false
enabled: true
#要迁移的JDBC URL,如果没有指定的话,将使用配置的主数据源.
url: jdbc:postgresql://localhost:5432/liquibase
#数据库用户名
user: postgres
#数据库密码
password: jmn123456@
#配置文件的路径,默认值为 classpath:/db/changelog/db.changelog-master.yaml
change-log: classpath:db/changeLog/changelog.xml
#检查 changelog 的位置是否存在,默认为true.
check-change-log-location: true
- 导入依赖
implementation 'org.liquibase:liquibase-core:3.6.3'
- 创建changelog文件并编写更改集(同上面三.2步骤)
<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.6.xsd">
<changeSet id="createStudentInfo" author="jmn">
<createTable tableName="student_info">
<column autoIncrement="true" name="id" remarks="主键ID" type="BIGSERIAL"/>
<column name="student_name" remarks="学生姓名" type="VARCHAR(16)"/>
<column name="sex" remarks="性别" type="SMALLINT"/>
<column name="age" remarks="年龄" type="VARCHAR(10)"/>
<column name="grade" remarks="成绩" type="INTEGER"/>
</createTable>
</changeSet>
<changeSet id="createUserInfo" author="jmn">
<sqlFile path="../sql/user_info.sql" relativeToChangelogFile="true"/>
</changeSet>
</databaseChangeLog>
- 启动项目
启动日志:
数据库:
新增了 student_info 表和 user_info 表,另外还多了两张表:databasechangelog、databasechangeloglock
五、gradle + liquibase插件
- 添加gradle插件
plugins {
id "org.liquibase.gradle" version "2.0.1"
}
- 配置依赖
liquibaseRuntime 'org.liquibase:liquibase-core:3.6.3'
liquibaseRuntime 'org.liquibase:liquibase-groovy-dsl:2.0.1' //不添加则报错
liquibaseRuntime 'ch.qos.logback:logback-classic:1.2.3' //不添加则报错
liquibaseRuntime 'org.postgresql:postgresql'
注:2、3依赖不添加,使用liquibase command则会报如下异常,原因详情。
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: ch/qos/logback/core/filter/Filter
- 配置 liquibase activities(类似profile)
liquibase {
activities {
dev {
changeLogFile "src/main/resources/db/changeLog/changelog.xml"
url "jdbc:postgresql://localhost:5432/liquibase"
username "postgres"
password "jmn123456"
}
test {
changeLogFile "src/main/resources/db/changeLog/changelog.xml"
url "jdbc:postgresql://localhost:5432/liquibase-test"
username "postgres"
password "jmn123456"
}
}
runList = System.getProperty("runList") ?: 'dev'
}
- liquibase的一些命令使用
配置好如上三步以后,可以使用gradle+liquibase command,并且指定环境:
-
update:修改数据库
$ gradle update -DrunList=dev
与springboot中接入后启动项目的效果一致,会执行changeLogFile里的changeSet,同时在数据库里生成databasechangelog 和 databasechangeloglock 两张表。
- generateChangeLog:生成ChangeLog文件
该命令可以用于在现有项目中接入liquibase,也就是现有项目已经有一些数据库表了,generateChangeLog 命令和 changeLogSync 命令可以将现有的数据库表按照表、索引等维度插入到 databasechangelog 表中
$ gradle generateChangeLog -DrunList=data
执行该命令时需要换一个changeLogFile路径,填写一个需要生成的文件名称,例:changelog-data.xml
-
changelogSync:将所有更改在数据库中标记为已执行
$ gradle changelogSync -DrunList=data
-
diff:数据库对比,报告模式输出两个数据库的差异
-
diffChangeLog:数据库对比,ChangeLog模式输出两个数据库的差异
使用该命令则需要在gradle的liquibase的配置中增加一个对比库
liquibase {
activities {
diff {
changeLogFile "src/main/resources/db/changeLog/changelog-diff.xml"
url "jdbc:postgresql://localhost:5432/liquibase"
username "postgres"
password "jmn123456"
referenceUrl 'jdbc:postgresql://localhost:5432/postgres'
referenceUsername 'postgres'
referencePassword 'jmn123456'
diffTypes 'tables,columns'
}
}
runList = System.getProperty("runList") ?: 'diff'
}
可以使用diff命令的diffTypes参数控制要检查的更改。以下选项可用,可以作为逗号分隔列表传递:
tables、columns、views、primaryKeys、indexes、foreignKeys、sequences、data
注意,官网上有这样一句话:这仅适用于“generateChangeLog”命令,而不适用于“diff”或“diffChangeLog”命令。
六、跨库迁移
- 使用 generateChangeLog 命令,增加 diffTypes 参数值为 data,可以将库中的表及数据导出到 changeLog文件中
- 再使用 update 命令将 changeLog 文件中的数据更新至新库
二者命令可以通过 activities 配置来配置不同的数据库连接。
七、跨数据库类型迁移
官网没有找到此种需求的描述,但是网上有搜到一两篇这样操作的文档,但年限都比较久,试了一下没有成功。按大家对 liquibase 的描述应该是支持的,还需要再深入研究。