liquibase 数据库版本留痕解决方案,在实际生产过程中如何高效管理数据库的DDL与DML语句,对这些语句留痕处理。如果能将sql的执行与SpringBoot项目启动结合在一起,每次启动项目自动执行新增的sql语句,这样就可以使得项目组成员各个都保持相同的开发库,避免人为操作导致数据库不符合预期。
文章目录
- 一,准备工作
- 二,准备changelog-master
- 三,准备changelog_init文件
- 四,准备自己的changelog文件
- 五,liquibase执行原理
一,准备工作
<!-- 首先引入liquibase依赖, 版本推荐4.5.0以上 -->
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.5.0</version>
</dependency>
<!-- 接着引入liquibase插件, 如果你的数据库已经有表和数据了可以使用该插件反向生成xml文件 -->
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<propertyFile>src/main/resources/db/liquibase.properties</propertyFile>
<propertyFileWillOverride>true</propertyFileWillOverride>
<outputChangeLogFile>src/main/resources/liquibase/changelog/changelog_init.xml</outputChangeLogFile>
</configuration>
</plugin>
outputChangeLogFile
标签指定后续插件生成的脚本存放目录,插件中指定了一个src/main/resources/db/liquibase.properties
的路径配置文件,配置文件内容如下:
# liquibase
changeLogFile=src/main/resources/liquibase/changelog-master.xml
# MySql
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/reggie?characterEncoding=utf-8&serverTimezone=UTC
username=root
password=mysqlroot
二,准备changelog-master
根据自己喜好,在resources目录下创建changelog目录,也就是liquibase目录,推荐使用resources->db->changelog->changelog_init.xml
这样的目录结构,我的目录结构如下:
changelog-master是整个liquibase的核心,SpringBoot项目启动的时候会自动去寻找这个文件,当然我们需要现在SpringBoot配置文件中启用liquibase
spring.liquibase.enabled=true
spring.liquibase.change-log=classpath:db/changelog-master.xml
有了master文件之后我们就可以把我们的sql文件写入或导入其中,或者指向另一个changelog的地址以区分不同的版本,目前我是指向了其他的changelog文件
<!-- changelog-master -->
<?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
https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.5.xsd">
<include file="classpath:db/changelog/changelog_init.xml"/>
<include file="classpath:db/changelog/changelog_v1.0.xml"/>
</databaseChangeLog>
这样SpringBoot项目启动的时候就会去读取我的changelog-master
文件,读取之后他会发现我这个文件引入了其他两个文件,他会按照先后顺序去读取这两个文件的内容,这样后续每一个大版本都可以用一个changelog来管理。
如果启动报错,找不到指定文件,可以参考这篇博客:https://blog.csdn.net/zy_zhangruichen/article/details/128540204
三,准备changelog_init文件
前面说过如果我们的项目是中途想引入liquibase,数据库此时已经有了表和数据怎么办?那我们需要把数据库导出成liquibase能够识别的格式,然后作为xml文件交给liquibase,让其帮我们管理。
如果配置了第一步的插件,那我们直接点击idea右侧的maven,选择plugins,然后liquibase:generateChangeLog:
那么liquibase就会自动帮我们生成一个初始化的文件,将这个文件作为changelog_init.xml
交给liquibase管理即可,但这种生成的文件只包含DDL语句,并没有数据的INSERT语句,需要自己手动处理。
四,准备自己的changelog文件
开发过程中,如果有需要提交的DDL语句或DML语句,可以按版本规划先写一个changelog文件,接着在这个changelog文件中引入sql或直接在标签中填入sql:
<!-- changelog_v1.0.xml -->
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<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
https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.5.xsd">
<!--
changeset:一个changelog可以包含多个changeset标签,每个changeset都由id、author、filepath属性唯一标识,
当liquibase执行数据库changeLog时,他会按顺序读取changeSet,并针对每个changeSet检查databasechangelog表,
已查看是否已经运行过id/author/filepath的组合,如果已运行且没有runAlways标签则会跳过该changeSet
author:作者
id:最好使用<项目名-时间戳>来命名区分
runAlways:执行每次运行时设置的更改,即使之前已经运行过了
context:灵活控制脚本在哪些环境中执行
-->
<changeSet id="reference-20230101-1400" author="y">
<sqlFile path="../sql/mysql_init_data.sql" relativeToChangelogFile="true" />
</changeSet>
<changeSet id="reference-20230103-2122" author="y">
<sqlFile path="../sql/mysql_dml_data_v1-1.sql" relativeToChangelogFile="true" />
</changeSet>
<changeSet id="reference-20230107-1951" author="y">
<sqlFile path="../sql/mysql_ddl_data_v1-1.sql" relativeToChangelogFile="true" />
</changeSet>
<changeSet id="reference-20230107-1952" author="y">
<sqlFile path="../sql/mysql_dml_data_v1-2.sql" relativeToChangelogFile="true" />
</changeSet>
<changeSet id="reference-20230107-2101" author="y">
<sql>
ALTER TABLE ticket MODIFY COLUMN `DATE` DATETIME;
</sql>
</changeSet>
<changeSet id="reference-20230107-2257" author="y">
<sql>
ALTER TABLE ticket ADD COLUMN `createtime` DATETIME COMMENT '创建时间';
ALTER TABLE ticket ADD COLUMN `updatetime` DATETIME COMMENT '更新时间';
</sql>
</changeSet>
<changeSet id="reference-20230108-1245" author="y">
<sql>
ALTER TABLE ticket ADD COLUMN version INT(10) DEFAULT 1 COMMENT '版本号';
</sql>
</changeSet>
<changeSet id="reference-20230108-1347" author="y">
<sql>
ALTER TABLE ticket ADD COLUMN isdeleted INT(1) DEFAULT 0 COMMENT '逻辑删除,0未删除,1已删除';
</sql>
</changeSet>
</databaseChangeLog>
五,liquibase执行原理
liquibase是怎么做到执行过的sql不再执行呢,其实在SpringBoot项目启动之后,它会在数据库中新增两张表,分别是DATABASECHANGELOG
和DATABASECHANGELOGLOCK
,前面这张表会把我们的changelog文件执行记录都记录下来,并生成md5秘钥,每次启动的时候会判断md5值是否相等,所以sql文件一旦执行就不能修改了,而后面这张表是数据库分布式锁的解决方案。