一、前言
一般在我们开发项目的时候经常会更新数据库表的字段,如果同事 a 添加了表字段,没有及时给同事 b sql 脚本,可能同事 b 的代码运行就会报错,而且随着时间的推移,sql 脚本越来越多,项目上线的时候整理起来就很费时间,所以就有大佬级别的人物创造了 Flyway 这个数据库版本管理工具。Flyway 是一款开源的数据库版本管理工具,它更倾向于规约优于配置的方式。Flyway 可以独立于应用实现管理并跟踪数据库变更,支持数据库版本自动升级,并且有一套默认的规约,不需要复杂的配置,Migrations 可以写成 SQL 脚本,也可以写在 Java 代码中,不仅支持 Command Line 和 Java API,还支持 Build 构建工具和 Spring Boot 等,同时在分布式环境下能够安全可靠地升级数据库,同时也支持失败恢复等。
二、Flyway介绍
2.1 主要特性
1.普通 SQL:纯 SQL 脚本(包括占位符替换)没有专有的XML格式,没有锁定
2.无限制:使用 Java 代码来进行一些高级数据操作
3.零依赖:只需运行在 Java6(及以上)和数据库所需的 JDBC 驱动
4.约定优于配置:迁移时,自动查找系统文件和类路径中的 SQL 文件或 Java 类
5.高可靠性:在集群环境下进行数据库升级是安全可靠的
6.云支持:完全支持 Microsoft SQL Azure, Google Cloud SQL & App Engine、Heroku Postgres 和 Amazon RDS
7.自动迁移:使用 Flyway 提供的 API,让应用启动和迁移同时工作
8.快速失败:损坏的数据库或失败的迁移可以防止应用程序启动
9.数据库清理:在一个数据库中删除所有的表、视图、触发器,而不是删除数据库本身
2.2 运行原理
当 Flyway 连接数据库中的 schema 后,会先检查是否已存在 flyway_schema_history 表,如果没有则创建。该表用于跟踪数据库的状态,如数据迁移的版本,迁移成功状态等信息。
当 flyway_schema_history 存在后,Flyway 会扫描文件系统或应用中的 classpath 目录的数据迁移文件,然后根据它们的版本号进行按序迁移,如下图:
由于 flyway_schema_history 表中记录了迁移的版本号,如果文件的版本号小于或等于标记为当前版本的版本号,则忽略它们不执行。
在实际使用中,flyway有两种方式执行,一种是构建项目的时候执行,一种是项目启动的时候执行。
上边描述的内容或许对读者来说还不够直观,那么下面我们就开始进行实战演练。
三、构建实战
环境:
mysql-5.7.30
springboot 2.3.5.RELEASE
新建一个 Maven 项目。
3.1 添加依赖
1 | <dependency> |
注意
:如果构件项目的时候执行Flyway,那么就必须引入spring-boot-starter-jdbc依赖。
3.2 配置数据迁移文件
在项目的 src/main/resources 下创建 db/migration 目录,该目录下放置需要数据迁移的文件。
数据迁移文件默认名称格式为:V[version]__[name].sql。
注意
:名称中[version]和[name]之间是两个下划线!
本次测试新建名为 V0.1.0__init_table.sql 的文件,内容如下:
1 | USE FLYWAYDB; |
我们再新建一个名为 V0.1.1__init_data.sql 文件,内容如下:
1 | INSERT INTO user (id, name, age, email) VALUES |
版本 1 数据迁移的内容是创建一张 user 表。
3.3 配置application.yml
1 | spring: |
图中,数据库 flywaydb 中创建了 flywayinit 表和 user 表,数据成功迁移到指定数据库中。
当系统升级时又需要做数据迁移,我们只需在 db/migration 目录下再放置新版本的 sql 文件即可。
版本 0.1.1 的数据迁移内容是往 user 表中插入 3 条数据。
上面我们在application.yml配置了flyway初始化的数据库,其实也可以配置好多相关参数,具体如下:
配置项 | 含义 |
---|---|
flyway.baseline-description | 对执行迁移时基准版本的描述. |
flyway.baseline-on-migrate | 当迁移时发现目标schema非空,而且带有没有元数据的表时,是否自动执行基准迁移,默认false. |
flyway.baseline-version | 开始执行基准迁移时对现有的schema的版本打标签,默认值为1. |
flyway.check-location | 检查迁移脚本的位置是否存在,默认false. |
flyway.clean-on-validation-error | 当发现校验错误时是否自动调用clean,默认false. |
flyway.enabled | 是否开启flywary,默认true. |
flyway.encoding | 设置迁移时的编码,默认UTF-8. |
flyway.ignore-failed-future-migration | 当读取元数据表时是否忽略错误的迁移,默认false. |
flyway.init-sqls | 当初始化好连接时要执行的SQL. |
flyway.locations | 迁移脚本的位置,默认db/migration. |
flyway.out-of-order | 是否允许无序的迁移,默认false. |
flyway.password | 目标数据库的密码. |
flyway.placeholder-prefix | 设置每个placeholder的前缀,默认${. |
flyway.placeholder-replacementplaceholders | 是否要被替换,默认true. |
flyway.placeholder-suffix | 设置每个placeholder的后缀,默认}. |
flyway.placeholders.[placeholder name] | 设置placeholder的value |
flyway.schemas | 设定需要flywary迁移的schema,大小写敏感,默认为连接默认的schema. |
flyway.sql-migration-prefix | 迁移文件的前缀,默认为V. |
flyway.sql-migration-separator | 迁移脚本的文件名分隔符,默认__ |
flyway.sql-migration-suffix | 迁移脚本的后缀,默认为.sql |
flyway.table | flyway使用的元数据表名,默认为schema_version |
flyway.target | 迁移时使用的目标版本,默认为latest version |
flyway.url | 迁移时使用的JDBC URL,如果没有指定的话,将使用配置的主数据源 |
flyway.user | 迁移数据库的用户名 |
flyway.validate-on-migrate | 迁移时是否校验,默认为true. |
四、启动方式实践
4.1 引入依赖
1 | <dependency> |
4.2 修改application.yml
1 | spring: |
4.3 编码
创建配置类FlywayConfig.java
1 | @Configuration |
在构建flyway的时候,构件方法和配置中的配置项类似。