mysql数据库版本管理_Liquibase-数据库版本管理使用

Liquibase-数据库版本管理

一、数据库版本管理说明

数据库迁移工具很多,这里我们选择Flyway和Liquibase来说主要是两个原因,

一是它们都是Java生态圈的,其次就是Spring Boot提供了这两者的内建支持,可以很快应用到产品中。

1、liquibase介绍

LiquiBase是一个用于数据库重构和迁移的开源工具,通过日志文件的形式记录数据库的变更,然后执行日志文件中的修改,将数据库更新或回滚到一致的状态。

LiquiBase的主要特点有:

支持几乎所有主流的数据库,如MySQL, PostgreSQL, Oracle, Sql Server, DB2等

支持多开发者的协作维护

日志文件支持多种格式,如XML, YAML, JSON, SQL等

支持多种运行方式,如命令行、Spring集成、Maven插件、Gradle插件等

1.1、changelog文件格式

changelog是LiquiBase用来记录数据库的变更,一般放在CLASSPATH下,然后配置到执行路径中。

changelog支持多种格式,主要有XML/JSON/YAML/SQL,其中XML/JSON/YAML除了具体格式语法不同,节点配置很类似,SQL格式中主要记录SQL语句,以下示例仅给出SQL格式的示例,更多的格式示例请参考文档

2、flyway介绍

flyway相对简单,直接将你需要执行的SQL语句保存为文件,放入应用中执行即可。

Flyway的好处在于简单,而且直接书写SQL并不需要额外的学习。社区版的不支持UNDO操作,需要购买企业版。

3、liquibase与flyway比较

Flyway 自动升级(自动发现更新项):Flyway 会将任意版本的数据库升级到最新版本。

Flyway 可以脱离JVM 环境通过命令行执行,可以通过Ant 脚本执行,通过Maven 脚本执行(这样就可以在集成环境自动执行),并且可以在应用中执行(比如在应用启动时执行)。

Flyway 规约优于配置:Flyway 有一套默认的规约,所以不需要修改任何配置就可以正常使用。

Flyway 既支持SQL 脚本,又支持Java 代码:可以使用SQL 脚本执行数据库更新,也可以使用Java 代码来进行一些高级数据升级操作。

Flyway 高可靠性:在集群环境下进行数据库升级是安全可靠的。

Flyway 支持清除已存在的库表结构:Flyway 可以清除已存在的库表结构,可以从零开始搭建您的库表结构,并管理您的数据库版本升级工作

Flyway 支持失败修复。新的2.0 版本提供了repair 功能,用于解决数据库更新操作失败问题。

Liquibase 自动升级,将任意版本的数据库升级到最新版本。

Liquibase 可以根据数据库的情况为你生成最后的迁移语句,同时因为数据库变动首先是被Liquibase解析,所以也可以简单支持回滚。

Liquibase 支持大部分常见的数据库变动操作,比如建表,删表,变动字段等等

Liquibase 可以在不使用SQL的情况下造成数据库变动,其可读性更高一些,特别是团队并不直接使用SQL而整体相关知识储备不完善的情况下优势更明显。

两款数据库迁移工具其实定位上是差别的。一般小项目整体变动不大的用Flyway,大应用和企业应用用Liquibase更合适。

二、spring boot + liquibase

注:spring boot + liquibase此方式仅仅是简单的实现更新数据库表结构,用于启动项目时更新表结构。

1、gradle配置引入liquibase包:

dependencies {

compile group: 'org.liquibase', name: 'liquibase-core', version: '3.5.3'

testCompile group: 'junit', name: 'junit', version: '4.12'

}

2、修改application.yml或加LiquibaseConfig.java

2.1、application.yml

liquibase:

change-log: classpath:/db/changelog/master.xml

user: root

password: 1qaz2wsx

url: jdbc:mysql://127.0.0.1:3306/test_1.0.1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullNamePatternMatchesAll=true&useSSL=true

drop-first: false

2.2、LiquibaseConfig.java

@Configuration

public class LiquibaseConfig {

@Bean

public SpringLiquibase liquibase(DataSource dataSource) {

SpringLiquibase liquibase = new SpringLiquibase();

liquibase.setDataSource(dataSource);

liquibase.setChangeLog("classpath:/db/changelog/master.xml");

liquibase.setContexts("development,test,production");

liquibase.setShouldRun(true);

return liquibase;

}

}

3、新增changelog.xml

3.1、新增master.xml

在src/main.resouces下新增db/changelog/master.xml。

master.xml内容如下:

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.5.xsd">

3.2、新增V1.1__init.sql(以sql语句方式,也可以用xml、yml、json请查看官网)

在src/main.resouces/db/changelog下新增db/changelog/V1.1__init.sql。

V1.1__init.sql内容如下:

--liquibase formatted sql

--changeset whx:1.1

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------

-- Table structure for test_user_tab

-- ----------------------------

DROP TABLE IF EXISTS `test_user_tab`;

CREATE TABLE `test_user_tab` (

`userId` int(11) NOT NULL AUTO_INCREMENT,

`userAccount` varchar(16) NOT NULL,

`password` varchar(32) NOT NULL,

`userStatus` tinyint(1) NOT NULL DEFAULT '1',

`addTime` datetime NOT NULL,

PRIMARY KEY (`userId`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试用户表';

--changeset whx:1.2

ALTER TABLE `test_user_tab`

DROP COLUMN `addTime`;

--rollback ALTER TABLE `test_user_tab` ADD COLUMN `addTime` datetime NOT NULL AFTER `userStatus`;

--changeset whx:1.3

ALTER TABLE `test_user_tab`

ADD COLUMN `addTime` datetime NOT NULL AFTER `userStatus`;

--rollback ALTER TABLE `test_user_tab` DROP COLUMN `addTime`;

--changeset whx:1.4

ALTER TABLE `test_user_tab`

DROP COLUMN `addTime`;

--rollback ALTER TABLE `test_user_tab` ADD COLUMN `addTime` datetime NOT NULL AFTER `userStatus`;

--changeset whx:1.5

ALTER TABLE `test_user_tab`

ADD COLUMN `addTime` datetime NOT NULL AFTER `userStatus`;

--rollback ALTER TABLE `test_user_tab` DROP COLUMN `addTime`;

启动项目可以查看数据库此时新增了三张表:

databasechangelog

databasechangeloglock

test_user_tab

三、gradle + liquibase插件

1、修改build.gradle文件

1.1、多模块项目在根路径修改build.gradle

注:此方式将使所有model都有liquibase插件,在执行命令可能因为文件重复导致失败,不建议此方式。

group = 'test'

version = '0.0.1-SNAPSHOT'

buildscript {

ext {

repositories {

mavenCentral()

maven {

url "https://plugins.gradle.org/m2/"

}

}

dependencies {

classpath "gradle.plugin.org.liquibase:liquibase-gradle-plugin:2.0.1"

}

}

subprojects {

apply plugin: 'java'

apply plugin: 'eclipse'

apply plugin: "org.liquibase.gradle"

sourceCompatibility = 1.8

repositories {

mavenCentral()

maven {

url 'http://maven.aliyun.com/nexus/content/groups/public/'

}

}

dependencies {

liquibaseRuntime 'org.liquibase:liquibase-core:3.5.3'

liquibaseRuntime 'org.liquibase:liquibase-groovy-dsl:2.0.1'

liquibaseRuntime 'mysql:mysql-connector-java:5.1.34'

}

liquibase {

activities {

main {

changeLogFile "${this.rootDir}/user/src/main/resources/db/changelog/V1.1__init.sql"

url "jdbc:mysql://127.0.0.1:3306/test_1.0.1?useUnicode=true&characterEncoding=UTF-8"

username "root"

password "1qaz2wsx"

}

runList = 'main'

}

}

}

1.2、子模块修改build.gradle

例如:core model的core.gradle文件,推荐此方式。

group 'projectManage'

version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

buildscript {

repositories {

mavenCentral()

maven { url "https://plugins.gradle.org/m2/" }

}

dependencies {

classpath "org.liquibase:liquibase-gradle-plugin:2.0.1"

}

}

apply plugin: 'org.liquibase.gradle'

dependencies {

liquibaseRuntime 'org.liquibase:liquibase-core:3.5.3'

liquibaseRuntime 'org.liquibase:liquibase-groovy-dsl:2.0.1'

liquibaseRuntime 'mysql:mysql-connector-java:5.1.34'

compile project(":common")

testCompile group: 'junit', name: 'junit', version: '4.12'

liquibase {

activities {

main {

changeLogFile "${this.rootDir}/core/src/main/resources/db/changelog/V1.1__init.sql"

//changeLogFile "${this.rootDir}/core/src/main/resources/db/changelog/changelog.mysql.sql"

url "jdbc:mysql://127.0.0.1:3306/yb_oa_xmgl_1.0.1?useUnicode=true&characterEncoding=UTF-8"

username "root"

password "1qaz2wsx"

}

runList = 'main'

}

}

}

说明:

0、注意mysql驱动版本

liquibaseRuntime 'mysql:mysql-connector-java:5.1.34'

1、注意${this.rootDir}

changeLogFile "${this.rootDir}/user/src/main/resources/db/changelog/V1.1__init.sql"

如果不加${this.rootDir}可能会报Gradle Liquibase change log file could not be found

另一种写法:

liquibase {

activities {

main {

changeLogFile 'src/main/resources/db/dbchangelog-master.xml'

url 'jdbc:mysql://localhost:3306/test'

username 'XXX'

password 'XXX'

classpath "$rootDir"

}

}

runList = 'main'

}

2、命令示例

0、插件命令 gradle command -PliquibaseCommandValue= # -PliquibaseCommandValue= 为非填。

1、gradle update -PrunList=main #执行命令,将按V1.1__init.sql中的sql语句更新数据库。

2、gradle generateChangeLog #数据库sql文件的标准输出,执行于已存在表结构的数据库将会得到表数据结构文件。

注:changeLogFile 'src/main/resources/db/changelog.mysql.sql' ,changelog.xxx.sql允许不存在,执行时将自动创建。xxx代表的是数据库。

例如:changelog.h2.sql,必须是此格式,否则将报错。

3、gradle rollbackCount -PliquibaseCommandValue=1 # rollbackCount 回滚最后的更改集

4、gradle dbDoc # 将在/项目路径/.idea/dataSources下生成/xxx.xml文件,该文件是对数据库表数据结构的描述。

3、命令详解

liquibase官网:https://www.liquibase.org/documentation/command_line.html

注:插件命令 gradle command -PliquibaseCommandValue=

以下操作均已/core/src/main/resources/db/changelog/V1.1__init.sql中的V1.1__init.sql为例子。

3.1、数据库更新命令

命令描述

update

更新数据库到当前版本。

updateCount

更新数据库到指定的value版本,即第几个changeset。

例如:gradle updateCount -PliquibaseCommandValue=1

将只会执行V1.1__init.sql中--changeset whx:1.1,后续的changeset将不会执行。

若继续执行value=5,则--changeset whx:1.1~1.5都将执行,且之前的操作并不会冲突。

updateSQL

预执行sql(执行全部changeset),并不会更新数据库,仅在控制台输出。

updateCountSQL

预执行sql到指定的value版本。

3.2、数据库回滚命令

Liquibase有三种管理回滚的模式:

3.2.1、直接执行回滚

可以直接针对目标数据库执行回滚命令。如果无法回滚任何更改,您将收到通知,并且不会回滚任何更改。

3.2.2、生成回滚脚本

可以生成回滚数据库所需的SQL,而不是实际更新数据库。如果要预览在实际运行之前将执行的回滚命令,这将非常有用。

3.2.3、生成“未来回滚”脚本

此模式旨在允许在生成迁移脚本的同时生成回滚脚本。它允许获取更新的应用程序并生成SQL以将数据库更新为新版本以及SQL,以便在需要时将该新版本恢复到当前版本。当DBA想要控制进入数据库的SQL时,以及需要内部和/或“SOX兼容”进程的回滚文档的应用程序时,此功能非常有用。无需在此模式下指定回滚日期,标记或计数。

3.2.4 回滚命令

命令描述

rollback

要回滚到那个tag。例如:gradle rollback -PliquibaseCommandValue=tag20190107。

需要注意的是在V1.1__init.sql中,必须有--rollback。

例如:

--changeset whx:1.5

ALTER TABLE `test_user_tab`

ADD COLUMN `addTime` datetime NOT NULL AFTER `userStatus`;

--rollback ALTER TABLE `test_user_tab` DROP COLUMN `addTime`;

初始版本的sql数据表结构可以没有--rollback,但是后续的--changeset建议都加上--rollback。

rollbackToDate

设置回滚的日期。日期格式要符合插件执行theDateFormat.getDateInstance()操作设置的日期格式。

rollbackCount

value指定往前回滚几个版本,例如:gradle rollbackCount -PliquibaseCommandValue=1

将会回滚--changeset whx:1.5的操作。

rollbackSQL

根据tag,预执行rollback。并不会更新数据库,仅在控制台输出。

rollbackToDateSQL

根据date/time,预执行rollback。

rollbackCountSQL

根据value,预执行rollback。

futureRollbackSQL

SQL以在应用更改日志中的更改后将数据库回滚到当前状态。

updateTestingRollback

更新数据库,然后在更新之前回滚更改。

generateChangeLog

数据库sql文件的标准输出,执行于已存在表结构的数据库将会得到表数据结构文件。

注:changeLogFile 'src/main/resources/db/changelog.mysql.sql',

changelog.xxx.sql允许不存在,执行时将自动创建。xxx代表的是那种数据库。

例如:changelog.h2.sql,必须是此格式,否则将报错。

3.3、差异命令

diff命令用于比较数据库之间的异同。

注:它目前不检查:非外键约束(检查等)、存储过程、数据类型长度。

详见 3.11、liquibase.activities详解。

命令描述

diff [diff parameters]

将差异描述写入标准输出。

例如:gradle diff -PrunList=diffMain。

diffChangeLog [diff parameters]

写入更改日志XML以将基础数据库更新到目标数据库以标准输出,默认控制台输出。

例如:gradle diffChangeLog -PrunList=diffMain。

配置changeLogFile 则按规则输出。

3.4、文档命令

命令描述

dbDoc

默认将在/项目路径/.idea/dataSources下生成/xxx.xml文件,该文件是对数据库表数据结构的描述。

outputDirectory指定输出路径,不同后缀文件名将生产不同格式的Doc。

例如 gradle dbDoc -PliquibaseCommandValue=

D:\work_idea\yboa\pro_manage_dev\user\src\main\resources\db\changelog\123.sql

将生成html文件。

3.5、维护命令

命令描述

tag

"标记"当前数据库状态以供将来回滚。

例如:gradle tag -PliquibaseCommandValue=tag20190107

tagExists

检查给定标记是否已存在。

status

validate

检查更改日志中的错误。

changelogSync

将所有更改标记为在数据库中执行。

changelogSyncSQL

SQL以将在数据库中执行的所有更改标记为STDOUT。

markNextChangeSetRan

将下一个更改集标记为在数据库中执行。

listLocks

列出当前锁定数据库更改日志的人员。

releaseLocks

释放数据库更改日志上的所有锁定。

dropAll

删除用户拥有的所有数据库对象。请注意,不删除函数,过程和包(1.8.1中的限制)。

clearCheckSums

从数据库中删除当前的校验和。在下次运行时,将重新计算校验和。

3.6、必需参数

详见:build.gradle文件中的配置

命令描述

--changeLogFile=

要使用的changelog文件。

--username=

数据库用户名

--password=

数据库密码。

--url=

数据库JDBC URL。

--driver=

数据库驱动程序类名。

3.7、可选参数

命令描述

--classpath=

包含迁移文件和JDBC驱动程序的类路径。

--contexts=

ChangeSet上下文要执行。

--defaultSchemaName=

指定用于托管数据库对象和Liquibase控制表的默认架构。

--databaseClass=

指定要使用的自定义数据库实现

--defaultsFile=

包含默认选项值的文件。(默认值:./ liquibase.properties)

--includeSystemClasspath=

在Liquibase类路径中包含系统类路径。(默认值:true)

--promptForNonLocalDatabase=

提示非本地主机数据库。(默认值:false)

--currentDateTimeFunction=

覆盖SQL中使用的当前日期时间函数。适用于不受支持的数据库。

--logLevel=

执行日志级别((debug, info, warning, severe, off)。

--help

输出命令行参数帮助。

--exportDataDir

将保留insert语句csv文件的目录(generateChangeLog命令所需)。

--propertyProviderClass=

要使用的自定义Properties实现

3.8、必需的Diff参数

命令描述

--referenceUsername=

基础数据库用户名

--referencePassword=

基础数据库密码。

--referenceUrl=

基础数据库URL。

3.9、可选的Diff参数

命令描述

--referenceDriver=

基础数据库驱动程序类名。

3.10、更改日志属性

命令描述

-D=

传递名称/值对以替换更改日志中的$ {}块。

3.11、liquibase.activities详解

liquibase {

activities {

main {

changeLogFile "${this.rootDir}/core/src/main/resources/db/changelog/V1.1__init.sql"

//changeLogFile "${this.rootDir}/core/src/main/resources/db/changelog/changelog.mysql.sql"

url "jdbc:mysql://127.0.0.1:3306/yb_oa_xmgl_1.0.1?useUnicode=true&characterEncoding=UTF-8"

username "root"

password "1qaz2wsx"

//driver "" // 该参数可非必填,url将自动匹配驱动。

//exportDataDir // 将保留insert语句csv文件的目录(generateChangeLog命令所需)。

}

security {

changeLogFile 'src/main/db/security.groovy'

url project.ext.securityUrl

username project.ext.securityUsername

password project.ext.securityPassword

}

/**比较数据库之间的差异**/

diffMain {

//若不配置changeLogFile 则将在控制台进行xml输出。diff.mysql.sql会自动创建,必须以 *.databaseType.sql才会生成sql文件

changeLogFile "${this.rootDir}/core/src/main/resources/db/changelog/diff.mysql.sql"

url "jdbc:mysql://127.0.0.1:3306/yb_oa_xmgl_1.0.1?useUnicode=true&characterEncoding=UTF-8"

username "root"

password '1qaz2wsx'

referenceUrl "jdbc:mysql://127.0.0.1:3306/yb_oa_xmgl_1.0.2?useUnicode=true&characterEncoding=UTF-8"

referenceUsername "root"

referencePassword '1qaz2wsx'

}

runList = 'main' # 不同环境可执行不同的main方法, 例如:runList = 'diffMain'

}

}

4、插件升级

升级Liquibase Gradle插件本身的版本

大多数时候,Liquibase的新版本与旧版本的版本相同,但有时新版本与现有的更改集存在兼容性问题,就像Liquibase 3发布时一样。

发生这种情况时,建议执行以下升级程序:

1、确保所有Liquibase的管理数据库是最新通过运行 gradle update它们升级到Liquibase插件的新版本之前。

2、创建一个新的丢弃数据库来测试Liquibase更改集。gradle update使用最新版本的Liquibase插件在新数据库上运行 。

这很重要,因为Groovy DSL中的项目已弃用,并且因为不同Liquibase版本生成SQL的方式存在一些细微差别。

例如,使用defaultValue: "0"Liquibase 2中的工作正常,在MySql中向布尔列添加默认值,但在Liquibase 3中,

它生成的SQL不适用于MySql - defaultValueNumeric: 0需要使用它。

3、一旦确定所有更改集都使用最新的Liquibase插件,请清除所有由Liquibase 2旧版本计算的校验和,方法是gradle clearChecksums对所有数据库运行。

4、最后,gradle changeLogSync在所有数据库上运行以计算新的校验和。

你可能感兴趣的:(mysql数据库版本管理)