数据库版本管理工具flyway和liquibase

过去的,未来的
2020-01-02 / 2 评论 / 0 点赞 / 2,535 阅读 / 7,430 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2021-06-11,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

前言

从新开发软件到版本迭代可能会遇到的问题

  • 新版本开发过程中,开发人员的数据库变更如何更准确地反应到提交的文件中。(比如,A 在开发过程中添加了一个忘记写变动脚本的字段)
  • 某些预设的系统配置,没有设置的时候可能会出现错误。
  • 版本迭代的时候,老版本的数据库结构和数据的处理。

一、flyway

flyway

Flayway是一款数据库版本控制管理工具,,支持数据库版本自动升级,Migrations可以写成sql脚本,也可以写在java代码里;不仅支持Command Line和java api ,也支持Build构建工具和Spring boot,也可以在分布式环境下能够安全可靠安全地升级数据库,同时也支持失败恢复。

快速开始:

1、加入jar包
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
    <version>6.0.7</version>
</dependency>

<!-- 添加插件: -->
<plugin>
   <groupId>org.flywaydb</groupId>
   <artifactId>flyway-maven-plugin</artifactId>
</plugin>
2、加入配置
spring.datasource.url=jdbc:mysql://xxxxxx:3306/liquibase_db?useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=xxx
spring.datasource.password=xxx
3、加入执行sql (例如:V1.0.0_20191026_01__addTable.sql)
4、启动项目
5、特殊说明

1)配置不开启sql脚本管理

spring.flyway.enabled=false

2)Flyway加载Migrations的默认Locationsclasspath:db/migration可以配置更改。

spring.flyway.locations=classpath:db

3)默认生成了flyway-schema-history表,这个版本默认是这个表,如果想自己指定schema表的命,可以设置:

  spring.flyway.table=schema_version_user

4)命名规范 例如:V1.0.0_20191026_01__addTable.sql

  • prefix: 可配置,前缀标识,默认值V表示Versioned,R表示Repeatable
  • version: 标识版本号,由一个或多个数字构成,数字之间的分隔符可用点.或下划线_
  • separator: 可配置,用于分隔版本标识与描述信息,默认为两个下划线__
  • description: 描述信息,文字之间可以用下划线或空格分隔
  • suffix: 可配置,后续标识,默认为.sql

5)sql脚本尽可能可重复执行

6)对已经存在表结构数据的已有数据库使用flyway需要注意的几个地方。

 a、直接使用的话,启动时会报如下错误:
Caused by: org.flywaydb.core.api.FlywayException: Found non-empty schema(s) `test` without schema history     table! Use baseline() or set baselineOnMigrate to true to initialize the schema history table.

b、解决方案:设置setBaselineOnMigrate为true。

spring.flyway.baseline-on-migrate=true
c、但此时如果有脚本需要启动加载执行的话,脚本的版本号一定要比1大才能执行(注意红色标注),举个例子V1.0__Base_version.sql不会被执行,但V1.1__Base_version.sql就会被执行。

7)若执行sql脚本失败,flyway会记录失败信息到flyway_schema_history表,并且下次重新启动flyway前必须先删掉失败信息,否则会报错

8)若sql已经执行,建议不要在其上面再次需改(空格,换行可以使用),可以新建一个文件更新,必须要更改时,可以删除数据库记录,即可。(因为启动时,默认是有文件记录校验,这个配置也可以配置去除 , flyway.validate-on-migrate=false # 在运行迁移时是否要自动验证。 默认值: true)

9) 附录: Flyway配置详解

flyway.baseline-description= # 执行基线时标记已有Schema的描述
flyway.baseline-version=1 # 基线版本默认开始序号 默认为 1. 
flyway.baseline-on-migrate=false # 针对非空数据库是否默认调用基线版本 , 这也是我们上面版本号从 2 开始的原因
flyway.check-location=false # 是否开启脚本检查 检查脚本是否存在 默认false
flyway.clean-on-validation-error=false # 验证错误时 是否自动清除数据库 高危操作!!!
flyway.enabled=true # 是否启用 flyway.
flyway.encoding=UTF-8 # 脚本编码.
flyway.ignore-failed-future-migration=true # 在读元数据表时,是否忽略失败的后续迁移.
flyway.init-sqls= # S获取连接后立即执行初始化的SQL语句
flyway.locations=classpath:db/migration # 脚本位置, 默认为classpath: db/migration.
flyway.out-of-order=false # 是否允许乱序(out of order)迁移
flyway.placeholder-prefix= # 设置每个占位符的前缀。 默认值: ${ 。 
flyway.placeholder-replacement=true # 是否要替换占位符。 默认值: true 。 
flyway.placeholder-suffix=} # 设置占位符的后缀。 默认值: } 。 
flyway.placeholders.*= # 设置占位符的值。
flyway.schemas= # Flyway管理的Schema列表,区分大小写。默认连接对应的默认Schema。
flyway.sql-migration-prefix=V # 迁移脚本的文件名前缀。 默认值: V 。 
flyway.sql-migration-separator=__ # 迁移脚本的分割符 默认双下划线
flyway.sql-migration-suffix=.sql # 迁移脚本的后缀 默认 .sql
flyway.table=schema_version # Flyway使用的Schema元数据表名称 默认schema_version
flyway.url= # 待迁移的数据库的JDBC URL。如果没有设置,就使用配置的主数据源。
flyway.user= # 待迁移数据库的登录用户。
flyway.password= # 待迁移数据库的登录用户密码。
flyway.validate-on-migrate=true # 在运行迁移时是否要自动验证。 默认值: true 。

二、liquibase

      [liquibase](http://www.liquibase.org)

LiquiBase是一个用于数据库重构和迁移的开源工具,通过日志文件的形式记录数据库的变更,然后执行日志文件中的修改,将数据库更新或回滚到一致的状态。它的目标是提供一种数据库类型无关的解决方案,通过执行schema类型的文件来达到迁移。其有点主要有以下:
  • 支持几乎所有主流的数据库,如MySQL, PostgreSQL, Oracle, Sql Server, DB2等;
  • 支持多开发者的协作维护;
  • 日志文件支持多种格式,如XML, YAML, JSON, SQL等;
  • 支持多种运行方式,如命令行、Spring集成、Maven插件、Gradle插件等。

快速开始:

1、加入jar包
<dependency>
   <groupId>org.liquibase</groupId>
   <artifactId>liquibase-core</artifactId>
   <version>3.8.0</version>
</dependency>
2、加入配置
spring.datasource.url=jdbc:mysql://xxxxxx:3306/liquibase_db?useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=xxx
spring.datasource.password=xxx
spring.liquibase.change-log=classpath:db/changelog.xml

增加文件changelog.xml

<?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.4.xsd">

    <include file="changelog/V1.0.0_20191026_01__addTable.sql" relativeToChangelogFile="true"/>

<!--
    <includeAll path="changelog"  relativeToChangelogFile="true" />
-->
</databaseChangeLog>
3、加入执行sql (例如:V1.0.0_20191026_01__addTable.sql)
4、启动项目
5、特殊说明

1)配置不开启sql脚本管理

spring.liquibase.enabled=false
2)默认生成了 DATABASECHANGELOG和  DATABASECHANGELOGLOCK  表,这个版本默认是这个表,如果想自己指定schema表的命,可以设置:

第一种:

spring.liquibase.database-change-log-table=order-log
spring.liquibase.database-change-log-lock-table=order-lock

第二种:

@Configuration
public class LiquibaseConfiguration {
    /**
     *  订单模块Liquibase
     */
    @Bean
    public SpringLiquibase userLiquibase(DataSource dataSource) {
        SpringLiquibase liquibase = new SpringLiquibase();
        // 模块Liquibase文件路径
        liquibase.setChangeLog("classpath:db/changelog.xml");
        liquibase.setDataSource(dataSource);
        liquibase.setShouldRun(true);
        liquibase.setResourceLoader(new DefaultResourceLoader());
        // 覆盖Liquibase changelog表名
        liquibase.setDatabaseChangeLogTable("order_changelog_table");
        liquibase.setDatabaseChangeLogLockTable("order_changelog_lock_table");
        return liquibase;
    }

}

3)命名规范 例如:V1.0.0_20191026_01__addTable.sql

  • prefix: 可配置,前缀标识,默认值V表示Versioned,R表示Repeatable
  • version: 标识版本号,由一个或多个数字构成,数字之间的分隔符可用点.或下划线_
  • separator: 可配置,用于分隔版本标识与描述信息,默认为两个下划线__
  • description: 描述信息,文字之间可以用下划线或空格分隔
  • suffix: 可配置,后续标识,默认为.sql
    4)sql脚本尽可能可重复执行

5)创建了两个表:“databasechangelog”和“databasechangeloglock”。

databasechangelog表包含已针对数据库运行的所有语句的列表。
databasechangeloglock表用于确保两台计算机不会同时尝试修改数据库。

6)支持xml格式的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"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">

    <changeSet id="1" author="bob">
        <createTable tableName="department">
            <column name="id" type="int">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <column name="name" type="varchar(50)">
                <constraints nullable="false"/>
            </column>
            <column name="active" type="boolean" defaultValueBoolean="true"/>
        </createTable>
    </changeSet>

</databaseChangeLog>

7)relativeToChangelogFile说明:

 relativeToChangelogFile如果为true,则表示file属性表示的文件路径是相对于根changelog而不是CLASSPATH的,默认为false。

8)标签

<include>的file属性表示要包含的changelog文件的路径,这个文件可以是LiquiBase支持的任意格式
<includeAll>指定的是changelog的目录,而不是为文件;

9)Liquibase特性

  • 不依赖特定数据库,像Hibernate一样支持几乎所有的主流数据库如MySql,Oracle,PostgreSQL,H2等等支持数据库的操作非常丰富,如创建或修改 表(table)、视图(views)、索引(index)以及数据(data)等
  • 对数据库的变更描述支持多种格式XML、YAML、JSON等
  • 可以记录数据库的变更历史,是通过创建特定的表结果来实现这个功能
  • 可以diff两个数据库的差异
  • 可以轻松的把比如mysql库导出其他支持数据库的sql脚本
  • 支持java命令、Maven、Gradle、Spring Boot集成运行
  • 提供了Eclipse和IDEA的数据库重构插件,但是多年未更新不推荐使用

10)规范

ChangeSet id建议使用Flayway的命名格式V[_][__description],如V1.0_0__init。或使用[任务ID]-[日期]-[序号],如T100-20190705-001
ChangeSet必须填写author
Liquibase禁止对业务数据进行sql操作
所有表,列要加remarks进行注释
已经执行过的ChangeSet严禁修改。
不要随便升级项目liquibase版本,特别是大版本升级。不同版本ChangeSet MD5SUM的算法不一样。

三、 flyway和liquibase比较

1、用Flyway定义数据库迁移过程

1)优点:SQL用起来便捷顺手。

2)缺点:无法跨平台使用。

原因(sql方言): 不同的数据库,比如Oracle,MSSQL,MySQL
                它们的SQL会有少量的差别,内置函数也会有点不同
                  比如top子句,在Oracle里面就不能用,
2.、用Liquibase定义数据库迁移过程
  1)优点:可以跨平台使用和它的其他特性

  2)缺点:迁移脚本需要花费精力去维护
3、总结
  > 两款数据库迁移工具其实定位上是差别的,一般我的倾向是小项目,整体变动不大的用Flyway,而大应用和企业应用用Liquibase更合适。

附录

DELIMITER $$

DROP PROCEDURE IF EXISTS `p_execute_sql_ignore_error`$$

CREATE PROCEDURE `p_execute_sql_ignore_error`(v_sql VARCHAR(3000))
    SQL SECURITY INVOKER
    COMMENT '执行某个sql语句(忽略错误)'
BEGIN
 DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
   SET @r_status = 'error';

 SET @r_status = 'success';
 SET @v_sql = v_sql;

 PREPARE stmt FROM @v_sql;
 EXECUTE stmt;

 DEALLOCATE PREPARE stmt;

END$$

DELIMITER ;
0

评论区