springboot+flyway实现数据库脚本迁移【mysql】


功能:数据库脚本迁移工具

使用场景:

  1. 本地数据库开发模式下,开发人员A对数据库表结构进行了修改,并修改了对应的dao层的代码,开发人员B更新了A的代码,确没有运行对应的对应的数据库脚本就会导致程序报错。
  2. 项目上线、者项目部署或者项目更新时,也需要维护人员去运行大量的数据库脚本。

使用方法:

把SQL脚本放在resource/db/migration文件夹下,应用会在启动时自动根据flyway_schema_history【应用第一次集成flyway时生成】的执行情况自动辨别并执行脚本

开始使用

1. pom


        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
            <version>5.2.4</version>
        </dependency>

2. yml配置

这些配置都可以在org.flywaydb.core.api.configuration中可以看到

  datasource:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/springclouddemo?useUnicode=true&characterEncoding=utf-8&useSSL=true
      username: root
      password: 123456
  flyway:
    # 是否启用flyway
    enabled: true
    ## 编码格式,默认UTF-8
    encoding: UTF-8
    ## 迁移sql脚本文件存放路径,默认db/migration
    locations: classpath:db/migration
    ## 迁移sql脚本文件名称的前缀,默认V
    sqlMigrationPrefix: V
    ## 迁移sql脚本文件名称的分隔符,默认2个下划线__
    sqlMigrationSeparator: __
    # 迁移sql脚本文件名称的后缀
    sqlMigrationSuffixes: .sql
    # 迁移时是否进行校验,默认true
    validateOnMigrate: true
    # 设置为true,当迁移发现数据库非空且存在没有元数据的表时,自动执行基准迁移,新建schema_version表
    baselineOnMigrate: true

3. 在resource下新建db/migration文件夹,把数据库脚本放进去

4. 在应用启动时执行SQL脚本

命名规范

  1. V文件:V版本号__版本描述.sql
    V文件只会在同一个数据库执行一次
    例如:R2020.04.06__新增times字段.sql

  2. R文件:R版本号__版本描述.sql
    文件内容发生改变时就会被执行,执行顺序是在所有V文件执行完之后执行,因为每次内容发生改变时执行,所以编写DDL语句时需加上CREATE OR REPLACE。
    注意事项:
    版本号必须唯一.
    必须拥有数据库root账号权限。

    在5.2.2版本之后,flyway需要访问performance_schema.user_variables_by_thread,但是普通用户并没有相关权限,flyway的后续功能用不了。遇到次问题将flyway版本更换到5.2.1就好了

    应用会在启动时生成flyway_schema_history ,但如果此时已经集成了druid的并开启sql防火墙的话,druid会把生成该表的语句当成SQL注入过滤掉,因此需要在应用启动前先手动执行SQL。SQL脚本如下

DROP TABLE IF EXISTS `flyway_schema_history`;
CREATE TABLE `flyway_schema_history`  (
  `installed_rank` int(11) NOT NULL,
  `version` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
  `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `script` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `checksum` int(11) NULL DEFAULT NULL,
  `installed_by` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `installed_on` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  `execution_time` int(11) NOT NULL,
  `success` tinyint(1) NOT NULL,
  PRIMARY KEY (`installed_rank`) USING BTREE
) ENGINE = InnoDB

或者在jar包中也能找到这条语句

报错解决

报错内容如下

ERROR: Validate failed:
Migration checksum mismatch for migration version 1
-> Applied to database : 625057440
-> Resolved locally    : 1715188512

这种报错的指的是原有的checksum值和本次执行的checksum值对应不上,也就是数据不完整,就是flyway_schema_history中的记录在当前的存放脚本文件夹中不完整,
复现:
此时记录表中只有一条数据。
在这里插入图片描述
文件夹中只有一个脚本。

这时我把原来的脚本删了,同时新增另外一个脚本,注意不要flyway_schema_history中的记录,这时执行迁移就会报刚才的错误。

报错:FlywayException: Validate failed: Detected resolved migration not applied to database

原因:
flyway执行升级脚本是按版本号升序依次执行的, 如果版本号为201908080001__add_table.sql的脚本已经被执行了, 这时执行版本号小于该脚本的, 如201908060001__add_table.sql, flyway会抛出该异常
解决办法:修改版本号使大于当前版本号。

flyway使用过程中遇到的问题

  1. 大部分问题都是脚本校验不通过的问题,建议先把确保数据库脚本能运行无误,确保 * t_sys_schemas_version*中没有当前版本的运行记录。版本号一定不能相同,且要大于最新版本号

  2. 由于我们使用了shiro,且shiro中的过滤器是存在数据库中的,在应用启动的时候将过滤器链注入到shiro中,flyway脚本中也有一些新增加的过滤器链的配置,但是由于shiro是先于flyway执行,会导致shiro注入的过滤器链不完整,所以要使用CommonLineRunner 在应用启动后重新加载过滤器链。

  3. 解决方案:

    方案一:
    手写flyway配置执行类,设置执行顺序最先执行根据启动配置文件是否执行SQL迁移,dev环境不执行SQL迁移.
    方案二:
    手写flyway配置执行类
    @DependsOn("flywayConfig") // 这里指定依赖于 flywayConfig 类
    方案三
    启动完成后重新加载过滤器链
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rorschach01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值