1、简单介绍一下flyway
Flyway 是一款开源的数据库版本控制工具,主要用于管理数据库结构的变更(如创建表、修改字段、插入数据等)。它通过跟踪和执行版本化的迁移脚本,帮助团队实现数据库变更的自动化。接下来简单介绍一下flyway的工作流程:
1.1、 初始化阶段
-
检查元数据表
Flyway 首先检查目标数据库中是否存在flyway_schema_history
表(默认表名称,也可以自定义历史表名称)。-
不存在:自动创建该表,用于记录迁移历史
-
已存在:读取已有迁移记录
-
千万不要手动的修改历史表的任何数据,不然肯定会导致版本管理错误。
1.2、 迁移扫描
-
脚本加载
扫描配置的locations
路径(默认classpath:db/migration
),识别两类脚本:-
版本化迁移脚本(
V
开头) -
可重复迁移脚本(
R
开头)
-
1.3、校验阶段
-
校验 Checksum
对比已执行脚本的checksum
与本地文件的checksum
:-
若已执行脚本的 checksum 发生变化 → 抛出错误(防止篡改历史脚本)
-
校验通过 → 进入迁移阶段
-
1.4、 迁移执行
-
版本化迁移
按版本号顺序执行所有 未应用 的V
前缀脚本,且 仅执行一次 -
可重复迁移
按文件名顺序执行R
前缀脚本,当脚本内容变化时 重新执行
1.5、 更新元数据
每个成功执行的脚本会被记录到 flyway_schema_history
表,包含:
版本号
脚本名称
checksum
执行时间
执行状态
如图就是一个默认的历史表中数据。
在这里详细解释一个flyway中的两种字母开头的执行脚本的不同;
V
开头 vs R
开头脚本的区别
1. 版本化迁移脚本(V
前缀)
-
命名规则
V<Version>__<Description>.sql
(例如V1.2__Create_User_Table.sql
)-
Version
:唯一且不可变的版本号(建议使用语义化版本,如1.0.1
) -
Description
:人类可读的描述(使用下划线分隔单词)
-
-
核心特性
-
一次性执行:每个脚本仅执行一次
-
顺序敏感:按版本号顺序依次执行
-
内容不可变:已执行的脚本内容不可修改(否则校验失败)
-
-
典型场景
-
创建/修改表结构
-
新增索引或约束
-
一次性数据迁移(如初始化基础数据)
-
2. 可重复迁移脚本(R
前缀)
-
命名规则
R__<Description>.sql
(例如R__Update_Product_View.sql
)-
没有版本号
-
Description
:描述脚本作用(按字母顺序排序执行)
-
-
核心特性
-
重复执行:脚本内容变化时自动重新执行
-
顺序依赖:按文件名字母顺序执行
-
内容可变:允许修改后重新应用
-
-
典型场景
-
维护视图(View)或存储过程(Stored Procedure)
-
更新静态数据(如多环境差异化配置)
-
重建索引或物化视图
-
关键对比总结
特性 | V 前缀脚本 | R 前缀脚本 |
---|---|---|
执行次数 | 仅一次 | 内容变化时重复执行 |
版本号 | 必须唯一且递增 | 无版本号 |
内容修改 | 禁止修改(会导致校验失败) | 允许修改(触发重新执行) |
执行顺序 | 按版本号顺序 | 按文件名字母顺序 |
适用场景 | 结构变更、一次性操作 | 可重复逻辑、数据维护 |
最佳实践建议
-
版本化脚本 (
V
)-
使用语义化版本(如
V1.2.3
) -
每个脚本完成一个独立的变更任务
-
禁止修改已提交到代码仓库的
V
脚本
-
-
可重复脚本 (
R
)-
用于维护视图、存储过程等易变对象
-
通过文件名控制执行顺序(如
R__01_ViewA.sql
,R__02_ViewB.sql
) -
谨慎修改生产环境的
R
脚本(可能触发全量更新)
-
-
混合使用策略
-
用
V
脚本管理表结构变更 -
用
R
脚本管理视图和存储过程
-
示例:
db/migration/
├── V1.0__Create_Tables.sql
├── V1.1__Add_Indexes.sql
└── R__Update_Views.sql
-
校验保护
-
生产环境务必启用
validate-on-migrate: true
-
开发环境可开启
flyway.validate-migration-naming: true
强制命名校验
-
通过合理使用 V
和 R
脚本,可以实现数据库变更的 原子性 和 可追溯性,同时适应不同场景的灵活性需求。
2、使用spring boot项目整合flyway
2.1、新创建一个spring boot项目,并导入一些初始的依赖;
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.flywaydb</groupId><artifactId>flyway-core</artifactId><!-- 无需指定版本(Spring Boot 已管理) --></dependency><!-- druid连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.18</version></dependency><!-- MySQL--><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><!-- 无需指定版本(Spring Boot 已管理) --><dependency><groupId>org.flywaydb</groupId><artifactId>flyway-mysql</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version></dependency></dependencies>
需要注意的一点是,spring官方自动管理的flyway的版本,所以我们只需要指定spring的版本就自动会兼容合适的flyway版本,我的spring boot版本为3.3.9
我们主要使用到的依赖有三个:
flyway-core:flyway的核心依赖
flyway-mysql:指定数据库的类型
mybatis-spring-boot-starter: 数据源的自动配置,也可以是其他的依赖坐标。不一定要是mybatis,如JDBC、JPA等都可以
2.2、配置相应的yml配置文件
spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/testflyway?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTCusername: rootpassword: 123456flyway:enabled: truelocations: ["classpath:db/migration"] # 修正为数组格式table: flyway_schema_historybaseline-on-migrate: true # 必须启用(处理已有表场景)sql-migration-prefix: "V"sql-migration-separator: "__"sql-migration-suffixes: [".sql"] # 数组格式
logging:level:org.flywaydb: TRACE # 输出最详细日志
我们只需要配置一些flyway的属性,就可以直接使用flyway了。
2.3、编写相应的sql执行语句,并且存放在固定的文件地址
-- 创建用户表
CREATE TABLE IF NOT EXISTS user (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL UNIQUE,email VARCHAR(100) NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);-- 初始数据插入
INSERT INTO user (username, email) VALUES('admin', 'admin@example.com'),('user1', 'user1@example.com');
我这里就创建了一张数据表,并且插入了一些数据;
将SQL脚本放在合适的位置:
注意SQL脚本的存放位置不是乱放的,要符合我们之前在yml配置文件中书写的配置,SQL脚本的名称也不是随便取得,要符合flyway的命名规范。
2.4、运行spring boot项目
我们配置好了这些之后,就可以直接启动spring boot项目了。如果你是第一次启动项目,flyway会自动扫描相应文件夹下的SQL脚本,并在你的数据库中建立一个历史记录表 flyway_schema_history。要特别注意的是我们千万不要手动的修改这张表中的任何数据,flyway就是根据这张历史记录表来进行SQL脚本的执行等等一系列操作。
我们可以直接在控制台中看到flyway已经顺利的执行我们相应的SQL脚本
我们现在可以连接一下数据库来看看是否正确
可以看到数据库中已经有了相应的数据表,并且数据表中已经有了一些初始数据了
这个是我们第一次启动spring boot项目时自动执行的SQL脚本。那么等我们第二次启动时,flyway还是会扫描相应的SQL脚本,同时查询 flyway_schema_history
历史表,来判断SQL脚本要不要执行。当我们在此运行spring boot项目:
我们在控制台的日志中可以很清楚的看到flyway的执行过程。
3、总结
以上,就是我们使用spring boot整合flyway来进行数据库的版本管理。总体来说是非常简单的,我们只需要一些简单的配置和遵守一些flyway的命名规定就可以直接使用flyway了。这也是spring官方一直在努力推行的
约定大于配置,配置大于编码
当然,flyway的功能还有很多,这篇文章也只是初步帮你认识一下flyway。并且使用spring boot来简单的使用flyway的基本功能,但总的来说,我们几乎可以只通过一些配置文件中属性来使用flyway的绝大部分功能,一下我整理了一些常用的flyway属性,供大家参考:
spring:flyway:# 基础配置enabled: true # 是否启用 Flyway,默认 trueurl: jdbc:mysql://localhost:3306/db # 覆盖默认数据库连接(可选)user: root # 覆盖默认数据库用户(可选)password: root # 覆盖默认数据库密码(可选)# 脚本管理locations: # 迁移脚本路径(默认 classpath:db/migration)- classpath:db/migrations- filesystem:/opt/migrationsencoding: UTF-8 # 脚本文件编码,默认 UTF-8sql-migration-prefix: V # 版本迁移脚本前缀,默认 "V"repeatable-sql-migration-prefix: R # 可重复迁移脚本前缀,默认 "R"sql-migration-separator: __ # 脚本名称分隔符,默认双下划线sql-migration-suffixes: # 脚本后缀列表,默认 [".sql"]- .sql- .pgsql# 迁移规则schemas: public # Flyway 管理的 schema 列表(逗号分隔)table: flyway_history # 元数据表名,默认 "flyway_schema_history"baseline-on-migrate: false # 迁移时自动执行基线(默认 false)baseline-version: 1 # 基线版本号,默认 "1"baseline-description: Initial Setup # 基线描述target: latest # 目标版本(默认最新版本,可用版本号如 "3.1")out-of-order: false # 是否允许乱序执行迁移(默认 false)validate-on-migrate: true # 迁移时校验脚本(默认 true)ignore-missing-migrations: false # 忽略缺失的迁移记录(默认 false)# 占位符配置placeholder-replacement: true # 启用占位符替换(默认 true)placeholders: # 自定义占位符键值对key1: value1key2: value2# 高级配置clean-on-validation-error: false # 校验失败时自动执行 clean(危险!默认 false)connect-retries: 3 # 连接失败重试次数(默认 0)lock-retry-count: 50 # 获取锁的重试次数(默认 50)group: false # 将相同版本的迁移合并为单个事务(默认 false)mixed: false # 是否允许混合 DDL 和 DML(默认 false)skip-default-callbacks: false # 跳过默认回调(默认 false)skip-default-resolvers: false # 跳过默认解析器(默认 false)init-sqls: # 获取连接后立即执行的 SQL 语句- SET ROLE 'myuser'# 多环境配置示例
---
spring:profiles: prodflyway:url: jdbc:mysql://prod-db:3306/prod_dblocations:- "classpath:db/migration/common"- "classpath:db/migration/prod"ignore-migration-patterns: "*:pending"
关键配置说明:
-
基础配置:默认会复用
spring.datasource
配置,需要覆盖时单独指定 -
脚本管理:通过前缀/后缀/路径控制脚本识别规则
-
迁移规则:控制基线、校验、执行顺序等核心行为
-
生产环境注意事项:
-
clean-on-validation-error
应始终保持false
-
out-of-order
需谨慎启用 -
建议明确指定
target
版本控制生产环境迁移
-
-
最佳实践:
-
使用
classpath
和filesystem
组合路径管理脚本 -
通过
placeholders
实现环境差异化配置 -
启用校验确保迁移安全
-
可以通过 flyway.validateMigrationNaming
配置项(默认 false)开启严格的脚本命名校验,建议开发环境开启。
flyway的官网地址为:https://flywaydb.org/
你有如果想了解更多有关flyway的信息,可以直接访问官网