Liquibase-数据库版本管理控制
1. 简介
Liquibase是一个用于跟踪、管理和应用数据库变化的开源的数据库重构工具。它将所有数据库的变化(包括结构和数据)都保存在XML文件中,便于版本控制。
Liquibase使参与应用程序发布过程的任何人都可以轻松地:
- 不依赖于特定的数据库,Liquibase会自动适配目标数据库进行脚本初始化,目前支持至少30种主流数据库。
- 提供数据库比较功能,比较结果保存在XML中,基于该XML可以用Liquibase轻松部署或升级数据库。
- 以XML记录/存储数据库变化,其中以
author
和id
唯一标识一个变化(ChangSet),支持数据库变化的合并,因此支持多开发人员同时工作。 - 在数据库中保存数据库修改历史(DatabaseChangeHistory),在数据库升级时自动跳过已应用的变化(ChangSet)。
- 提供变化应用的回滚功能,可按时间、数量或标签(tag)回滚已应用的变化。通过这种方式,开发人员可轻易的还原数据库在任何时间点的状态。
- 可生成数据库修改文档(HTML格式)
- 提供数据重构的独立的IDE和Eclipse插件
- 将所有变化(包括结构和数据)存在XML文件中,便于版本控制的工具
springboot支持,只需要导入依赖。
application.yml配置(可选)
不配置,默认去resource/db/changelog下找db.changelog-mastert.yml文件
2. Quick Start
使用步骤
- step1: 创建一个数据库变更日志(change log)文件。
- step2: 在变更日志文件内部创建一个变更集(change set)。
- step3: 通过命令行或构建脚本对数据库进行变更集。
- step4: 检验数据库中的变更
面向spring开发,通过springboot 整合 liquibase 了解其作用。
2.1 添加maven依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.8.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
2.2 application.yaml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
username: root
password: 123456
liquibase:
# 指定配置文件路径
change-log: classpath:db/db.changelog-master.xml
# 覆盖本地 ddl dml
drop-first: true
# 是否启用
enabled: true
# 记录版本日志表
database-change-log-table: databasechangelog
# 记录版本改变lock表
database-change-log-lock-table: databasechangeloglock
2.3 添加 liquibase xml
db.changelog-master.xml
liquibase 配置文件入口,主要用来引用其他的
changelog.xml
,如下配置文件中的include
,当然也可以使用includeAll
来引用整个目录
<?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="classpath:db/changelog/changelog-init-0.0.1.xml"/>
</databaseChangeLog>
changelog-init-0.0.1.xml
主要记录了
ddl
的变化信息,比如 如下配置文件中创建了两个表role
和user
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="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-4.6.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.6.xsd">
<changeSet author="ludangxin" id="1662615627445-2">
<createTable tableName="role" remarks="角色信息表">
<column name="name" remarks="角色名称" type="VARCHAR(255)"/>
<column name="role_key" remarks="角色key" type="VARCHAR(255)"/>
</createTable>
</changeSet>
<changeSet author="ludangxin" id="1662615627445-3">
<createTable tableName="user" remarks="用户信息表">
<column name="id" type="INT" remarks="主键">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="username" type="VARCHAR(255)" remarks="用户名称"/>
<column name="password" type="VARCHAR(255)" remarks="密码"/>
<column name="age" type="INT" remarks="性别"/>
<column name="sex" type="VARCHAR(255)" remarks="性别"/>
<column name="role" type="VARCHAR(255)" remarks="角色"/>
<column name="create_time" type="DATETIME" defaultValueComputed="NOW()" remarks="创建时间"/>
</createTable>
</changeSet>
</databaseChangeLog>
2.4 启动测试
项目启动完成后,查看数据库如下图,我们在changelog-init-0.0.1.xml
文件中定义的脚本初始化到了数据库中
通过该demo快速的完成了springboot 集成 liquibase,且完成数据库的初始化。
2.5 测试changeset版本控制
前提是我们将
application.yml
中的drop-first
置为false
,因为drop-first=true
相当于每次都重置数据库
此时我们想在user表中新增一个create_by
字段,便直接在之前的changeset中添加了字段,如下图所示,然后启动项目看结果
启动时控制台报错信息如下:
报错信息是我们直接修改了changeset后导致md5值与之前的不匹配(直接在之前的changeset中做了修改)
liquibase如何判断 是同一changeset的?
author
和id
唯一标识一个变化(ChangSet)
liquibase是如何进行changeset版本控制的?
Liquibase
会对已经执行的changelog
的每一个changeSet
的内容进行md5
计算,生成的值是databasechanglog
表的MD5SUM
字段。
当重新启动Liquibase
时,会对每个changeSet
进行md5
值计算,与databasechanglog
表中的MD5SUM
字段进行对比,如果不一致,说明changeSet
值已经被修改,无法启动成功。
3. DDL操作
3.1 创建表
<changeSet author="ludangxin" id="20220908-1">
<createTable tableName="order" remarks="订单信息表">
<column name="id" remarks="主键" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="order_number" remarks="订单编号" type="VARCHAR(255)"/>
<column name="user_id" remarks="用户id" type="BIGINT"/>
</createTable>
</changeSet>
3.2 删除表
<changeSet author="ludangxin" id="20220908-2">
<dropTable tableName="order"/>
</changeSet>
3.3 修改表
3.3.1 添加字段
<changeSet author="ludangxin" id="20220908-3">
<addColumn tableName="order">
<column name="status" remarks="订单状态" type="INT" defaultValue="0"/>
</addColumn>
</changeSet>
3.3.2 删除字段
<changeSet author="ludangxin" id="20220908-4">
<dropColumn tableName="order" columnName="order_number"/>
</changeSet>
3.3.3 修改字段
<changeSet author="ludangxin" id="20220908-5">
<renameColumn tableName="order" oldColumnName="status" newColumnName="state" columnDataType="VARCHAR(10)" remarks="订单状态"/>
</changeSet>
修改字段类型 不建议使用 因为会把字段的其他信息搞丢,比如字段注释
<changeSet author="ludangxin" id="20220908-7">
<modifyDataType tableName="order" columnName="state" newDataType="INT" />
</changeSet>
4. DML操作
4.1 数据初始化
项目部署难免会有系统内置的数据,这时我们可以通过使用liquibase进行初始化
新建csv文件user-init-0.0.1.csv
"id","username","password","age","sex","role","create_time","create_by"
"111","张三","222","23","1","admin","2022-09-08 14:22:33","system"
"112","李四","333","26","1","admin","2022-09-08 14:22:33","system"
"113","王五","444","25","1","admin","2022-09-08 14:22:33","system"
使用loadData
标签进行数据的初始化
<changeSet author="ludangxin" id="20220908-8">
<loadData tableName="user" file="data/user-init-0.0.1.csv"
separator=","
encoding="UTF-8"
relativeToChangelogFile="true"/>
</changeSet>
4.2 新增数据
<changeSet author="ludangxin" id="20220908-6">
<insert tableName="order">
<column name="id" valueNumeric="666"/>
<column name="user_id" value="2222"/>
<column name="state" value="2"/>
</insert>
<insert tableName="order">
<column name="id" valueNumeric="888"/>
<column name="user_id" value="3333"/>
<column name="state" value="1"/>
</insert>
</changeSet>
4.3 初始化总是变动的数据
使用上述的loadData
标签加载数据,当数据发生变化时,直接修改csv文件进行发布时,会报错版本不一致。
这时可以使用loadUpdateData
标签进行处理,注意的是changeset
上需要加参数runOnChange="true"
(当数据发生改变时不去校验md5)如下
<changeSet author="ludangxin" id="20220908-9" runOnChange="true">
<loadUpdateData tableName="user" file="data/user-init-0.0.1.csv"
primaryKey="id"
separator=","
encoding="UTF-8"
relativeToChangelogFile="true"/>
</changeSet>
5. 集成maven
使用maven集成liquibase可以方便的通过liquibase maven plaugin实现很多功能。例如:脚本运行,生成文档,数据库差异比较等
5.1 添加 properties
添加properties 文件用来配置liquibase plugin的配置信息。例如 数据库的链接信息,配置文件路径的配置等
liquibase.properties
-- 数据库连接信息
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
username=root
password=123456
-- liquibse系统表 表名称配置
databaseChangeLogTableName=databasechangelog
databaseChangeLogLockTableName=databasechangeloglock
-- 输出文件路径配置
outputChangeLogFile=src/main/resources/db/changelog/changelog-output-0.0.1.xml
-- liuquibase xml文件路径指定
changeLogFile=src/main/resources/db/db.changelog-master.xml
5.2 修改pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.example</groupId>
<artifactId>liquibase-demo2</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<liquibase.version>4.8.0</liquibase.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>${liquibase.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>${liquibase.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<configuration>
<!--properties文件路径,该文件记录了数据库连接信息等-->
<propertyFile>src/main/resources/db/liquibase.properties</propertyFile>
<propertyFileWillOverride>true</propertyFileWillOverride>
</configuration>
</plugin>
</plugins>
</build>
</project>
6. plugin-逆向生成xml
通过liquibase maven 插件,从已有的数据库生成xml配置信息
通过idea的maven功能,找到 liquibase plugin,双击如图liquibase:generateChangeLog
选项,执行完成之后就会在properties
文件中配置的outputChangeLogFile
路径生成对应的xml文件,如下图所示
7. plugin-生成数据库修改文档
双击liquibase plugin面板中的liquibase:dbDoc
选项,会生成数据库修改文档,默认会生成到target
目录中,如下图所示
访问index.html
会展示如下页面,简直应有尽有
8. plugin-发布changelog
之前我们对changelog的编辑都需要通过启动项目来运行changelog,有时候我们可能想不重启项目便能将修改发布运行到数据库中
双击liquibase plugin面板中的liquibase:update
选项,便可以将修改同步到数据库中
注:这里有个bug(也可能不是bug,我目前还没找到对应的解决办法,如果您有解决方案,),通过plugin
发布changelog
时,由于我们在db.changelog-master
中include
的是classpath
路径,但是通过plugin
发布时会报错找不到include
的xml文件,此时我们可以通过设置相对路径来解决这个问题,比如<include file="classpath:changelog/changelog-init-0.0.1.xml" relativeToChangelogFile="true"/>
,然而这又引发了另外一个问题,plugin
和直接启动springboot项目生成的databasechangelog表中的filename字段值
不同,导致运行changelog
时报错,因为liquibase默认会比较同一filename
下的changeset
9. plugin-比较数据库差异
首先使用liquibase diff 功能前,我们在properties中加入参考的数据库 test3
配置信息
用于差异比较的数据库,以此数据库为准,生成diff xml
# 对比参考的数据库信息 (用于plugin-diff)
referenceUrl=jdbc:mysql://localhost:3306/test3?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
referenceDriver=com.mysql.cj.jdbc.Driver
referenceUsername=root
referencePassword=123456
# 生成的差异比较xml的输出路径
diffChangeLogFile=src/main/resources/db/changelog/changelog-diff-0.0.1.xml
我们先观察下两个数据库有什么样的差异,再验证生成的diff xml
两个数据库如下,差异都用红色框起来了。
然后再用liquibase插件看下生成的 diff xml信息
双击liquibase plugin面板中的liquibase:diff
选项,如下图所示
执行完毕后,查看diff xml 内容如下:
生成的xml文件符合预期,将与test3数据库的差异都生成到了diff xml中
Liquibase-数据库版本管理控制的更多相关文章
- 使用 Liquibase 管理数据库版本 - SpringBoot 2.7 .2 实战基础
优雅哥 SpringBoot 2.7 .2 实战基础 - 05 -使用 Liquibase 管理数据库版本 在企业开发中,数据库版本管理好像是一个伪命题,大多项目都是通过 Power Designer ...
- Spring Boot 2.x基础教程:使用Flyway管理数据库版本
之前已经介绍了很多在Spring Boot中使用MySQL的案例,包含了Spring Boot最原始的JdbcTemplate.Spring Data JPA以及我们国内最常用的MyBatis.同时, ...
- android——数据库版本升/降级问题
数据库版本升级 在开发android应用程序的时候,一般由于在我们开发的时候我们不知道以后会后什么新功能,也有可能增加业务逻辑(也就是更新),可想而知我们原来的数据库结构可能不适用已更新的应用,那么应 ...
- 查看mysql数据库版本方法总结
当你接手某个mysql数据库管理时,首先你需要查看维护的mysql数据库版本:当开发人员问你mysql数据库版本时,而恰好你又遗忘了,那么此时也需要去查看mysql数据库的版本............ ...
- Msyql-检测数据库版本
show variables like '%version%'; 数据库版本结果: "protocol_version","" "version&qu ...
- ios开发 数据库版本迁移手动更新迭代和自动更新迭代
数据库版本迁移顾名思义就是在原有的数据库中更新数据库,数据库中的数据保持不变对表的增.删.该.查. 数据持久化存储: plist文件(属性列表) preference(偏好设置) NSKeyedArc ...
- MYSQL 查看当前用户与数据库版本
问题一: 查看当前用户 select user(); 问题二: 查看数据库版本 select version();
- Red Gate系列之二 SQL Source Control 3.0.13.4214 Edition 数据库版本控制器 完全破解+使用教程
原文:Red Gate系列之二 SQL Source Control 3.0.13.4214 Edition 数据库版本控制器 完全破解+使用教程 Red Gate系列之二 SQL Source Co ...
- MS SQL 事物日志传送能否跨数据库版本吗?
SQL SERVER的事物日志传送(log shipping)功能,相信很多人都使用过或正在应用,这是MS SQL提供的一个非常强大的功能,一般需要一个主数据库服务器(primary/producti ...
- ios开发数据库版本迁移手动更新迭代和自动更新迭代艺术(二)
由于大家都热衷于对ios开发数据库版本迁移手动更新迭代和自动更新迭代艺术(一)的浏览下面我分享下我的源文件git仓库: 用法(这边我是对缓存的一些操作不需要可以省去):https://github.c ...
随机推荐
- VisionPro · C# · 图像显示十字光标
程序通过 CogRecordDisplay 显示控件显示视觉运行结果图像,当我们对调试时,可能需要用到图像中心十字对位光标. 本文通过VisionPro两个拟合线工具,一个拟合圆工具在图像中画出光标, ...
- HTML\Flex tips
相关文档 HTML:https://www.w3school.com.cn/html/index.asp bootstrap-css: https://v3.bootcss.com/css/#form ...
- application.yml 常用基本配置
前言 在平时的项目开发中,自己对application.yml的配置的写法较为熟悉,现在自己就application.yml常用的配置进行总结如下: 1.Tomcat 配置 server: #设置请求 ...
- 老掉牙的 synchronized 锁优化,一次给你讲清楚!
我们都知道 synchronized 关键字能实现线程安全,但是你知道这背后的原理是什么吗?今天我们就来讲一讲 synchronized 实现线程同步背后的原因,以及相关的锁优化策略吧. synchr ...
- Tapdata Cloud 版本上新 | 支持通知自配置,支持GP、MQ数据源,界面更友好!
Tapdata Cloud https://cloud.tapdata.net Tapdata Cloud 是国内首家异构数据库实时同步云平台,目前支持Oracle.MySQL.PG.SQL Serv ...
- spring boot 打包为war包方法
刚刚接触spring boot,其快速开发的特性吸引我去研究一下.于是我写了个demo,用spring boot内置的tomcat运行的很好,但是我需要把它部署到外部的tomcat中,于是从网上查找资 ...
- ClickHouse(04)如何搭建ClickHouse集群
ClickHouse集群的搭建和部署和单机的部署是类似的,主要在于配置的不一致,如果需要了解ClickHouse单机的安装设部署,可以看看这篇文章,ClickHouse(03)ClickHouse怎么 ...
- from Crypto.Cipher import AES报错
python 在 Windows下使用AES时要安装的是pycryptodome 模块 pip install pycryptodome python 在 Linux下使用AES时要安装的是pyc ...
- CTO与CIO选型数据中台的几大建议
企业数字化转型离不开企业数字化技术的配备.但企业在选择数字化技术时也面临着一个问题,就是如何在大胆采用先进的数字化技术和对技术进行投资之间找到平衡,将投资风险降到最低,毕竟错误的技术选型会给企业带来不 ...
- 乐观锁和悲观锁在kubernetes中的应用
数据竞争和竞态条件 Go并发中有两个重要的概念:数据竞争(data race)和竞争条件(race condition).在并发程序中,竞争问题可能是程序面临的最难也是最不容易发现的错误之一. 当有两 ...