Flyway SQL版本管理--快速入门

300 阅读4分钟

引言

小伙伴们,大家好,你们在做项目迭代时,用的什么工具管理数据库表 DDL 和 DML 变更的?怎么把开发环境的 SQL 变更同步到生产环境?今天介绍一下使用 flyway 管理我们的数据库版本,帮你轻松管理 SQL 版本。

P.S. 在公司内部项目上,我们用的是 阿里云DMS 管理,数据库申请、结构设计、数据变更&审批、查询都在 DMS 上完成,功能非常贴心。

快速使用

spring boot 3.x 集成 flywaydb

咱们要达到的效果:每次迭代开发阶段,把变更的 DDL 和 DML 写到 SQL 文件中,应用启动时,可以自动检查 SQL,并执行到数据库中。推进迭代到生产环境时,可以自动把 SQL 变更执行到生产库中。

引入依赖

pom.xml或者 build.gradle文件引入依赖

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

如果项目中使用的是其他类型的数据库,替换一下 flyway-mysqlflyway-数据库,当前支持的数据库包括 flyway-database-postgresqlflyway-sqlserverflyway-database-oceanbase等,更多依赖,可查看 flyway 的 maven 仓库。 :::success 💡 flyway 支持常见的数据库版本,查看官方文档了解更多... :::

配置

在配置文件application.ymlapplication.properties中配置 flyway 的参数。

spring:
  #  flyway 依赖数据源
  datasource:
    url: jdbc:mariadb://localhost:3306/ranmai
  # flyway 的配置
  flyway:
    enabled: true
    baselineOnMigrate: true
    validateOnMigrate: true
    baselineVersion: 1.0.0
    locations: classpath:db/migration

如上配置字段表示:

  • flyway.enabled: 是否打开 flyway 数据 SQL 迁移的开关
  • flyway.baselineOnMigrate:是否自动执行基线版本的开关
  • flyway.validateOnMigrate:执行 SQL 迁移时,是否校验 SQL 的有效性和签名地址是否正确
  • flyway.baselineVersion: 基线版本,可以不设置
  • flyway.location:要迁移的 SQL 在哪个文件夹
  • spring.datasource.xx:数据源的配置,flyway 做数据迁移时,需要使用数据源

完整的 flyway 配置,可以查看文件 org.springframework.boot.autoconfigure.flyway.FlywayProperties

写迁移的 SQL

在配置的 SQL 迁移的文件夹中,写每次迭代变更的 SQL文件,一次迭代可以写多个,文件名格式为V{版本号}__{描述信息}.sql比如:

  • V1.0.0__initSchema.sql
# create table setting
create table if not exists sys_setting
(
    id           bigint auto_increment primary key,
    gmt_create   timestamp default CURRENT_TIMESTAMP not null comment '创建时间',
    gmt_modified timestamp default CURRENT_TIMESTAMP not null comment '更新时间',
    code         varchar(32)                         not null comment '配置编码',
    value        varchar(1000)                       not null comment '配置值'
);
  • V1.0.1__updateDataType.sql
# update sys_setting value to text.
alter table sys_setting
    modify column value text;

执行

启动Spring Boot应用,查看执行日志,是否有如下信息,如果有,说明执行成功。

2024-08-13 11:52:12 [INFO][com.zaxxer.hikari.HikariDataSource:122]: HiKariPool - Start completed.
2024-08-13 11:52:12 [INFO][org.flywaydb.core.FlywayExecutor:37]: Database: jdbc:mysql://localhost:3306/ranmai (MySQL 8.4)
2024-08-13 11:52:12 [WARN][o.f.c.i.database.base.Database:41]: Flyway upgrade recommended: MySQL 8.4 is newer than this version of Flyway and support has not been tested. The latest supported version of MySQL is 8.1.
2024-08-13 11:52:12 [INFO][o.f.core.internal.command.DbValidate:37]: Successfully validated 2 migrations (execution time 00:00.043s)
2024-08-13 11:52:12 [INFO][o.f.core.internal.command.DbMigrate:37]: Current version of schema `ranmai`: << Empty Schema >>
2024-08-13 11:52:12 [INFO][o.f.core.internal.command.DbMigrate:37]: Migrating schema `ranmai` to version "1.0.0 - initSchema"
2024-08-13 11:52:12 [INFO][o.f.core.internal.command.DbMigrate:37]: Migrating schema `ranmai` to version "1.0.1 - updateDataType"
2024-08-13 11:52:12 [INFO][o.f.core.internal.command.DbMigrate:37]: Successfully applied 2 migrations to schema `ranmai`, now at version v1.0.1 (execution time 00:00.122s)

或者查看数据库表 flyway_schema_history�是否有执行记录 image.png 如果下次执行,flyway 会检查flyway_schema_history�中是否有执行记录,对应 SQL 文件的校验和是否一致,如果不一致会报错,如果一致会忽略该版本的执行。 :::success 💡 flyway 执行记录在 flyway_schema_history 表中,该表 flyway 会自动创建。 :::

集成 flyway maven 插件

pom.xml 文件中,引入配置

<project xmlns="...">
  <build>
    <plugins>
      <plugin>
        <groupId>org.flywaydb</groupId>
        <artifactId>flyway-maven-plugin</artifactId>
        <version>10.1.0</version>
        <configuration>
          <!-- 数据源相关的配置 -->
          <url>jdbc:h2:file:./target/foobar</url>
          <user>sa</user>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>2.2.224</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
</project>

同上步中,写好 SQL 迁移脚本,然后执行命令

mvn flyway:migrate

还是集成到 spring boot 中,用起来比较方便 😄

FAQ

多人添加SQL,导致出现同版本的 SQL脚本,执行冲突

团队多人一起做一个项目时,在开发环境很容易出现该问题,如果出现,后添加的 SQL 脚本文件,升级一下版本号,在继续执行即可。

已执行 SQL 文件变更SQL 内容,提示校验和不通过?

启动应用时,报错

Caused by: org.flywaydb.core.api.exception.FlywayValidateException: Validate failed: Migrations have failed validation
Migration checksum mismatch for migration version 1.0.0
-> Applied to database : -1794293023
-> Resolved locally    : -1901383139
Either revert the changes to the migration, or run repair to update the schema history.
Need more flexibility with validation rules? Learn more: https://rd.gt/3AbJUZE

解决:
1、先确认有冲突 SQL 是否有变更,如果有变更,通过添加新版本变更
2、快速解决方法,可以修改表 flyway_schema_history中修改对应版本的 checksum的值,改成最新的值,在确认无影响的前提下,再修改

select * from flyway_schema_history where version = '1.0.0';

flyway 没有 starter 包,怎么自动执行的呢

spring-boot-autoconfigure包已经包含了 Flyway 的自动化配置.当配置参数中有spring.flyway.enabled=true而且有 Flyway.classFlywayDataSourceCondition.class类时,就会自动触发 Flyway 的配置。

@AutoConfiguration(after = { DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
@ConditionalOnClass(Flyway.class)
@Conditional(FlywayDataSourceCondition.class)
@ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", matchIfMissing = true)
@Import(DatabaseInitializationDependencyConfigurer.class)
@ImportRuntimeHints(FlywayAutoConfigurationRuntimeHints.class)
public class FlywayAutoConfiguration {
  ...
}

参考