Flyway 原理与实战
Flyway 原理与使用
Flyway 是一个数据库版本迁移工具。
可以简单理解为:
Git → 管代码变更历史
Flyway → 管数据库变更历史理解 Flyway,核心记住一句话:
Migration 是否执行,看
flyway_schema_history中有没有成功记录;已经执行过的 Migration 有没有被修改,看 checksum 是否一致。
一、为什么需要 Flyway
数据库结构会不断变化:
CREATE TABLE sys_user (...);
ALTER TABLE sys_user
ADD COLUMN phone VARCHAR(20);
CREATE INDEX idx_user_phone
ON sys_user(phone);如果全部人工执行,很容易出现开发、测试、生产环境数据库结构不一致。
Flyway 的做法是把每次数据库变更做成一个版本:
V1__init.sql
V2__create_user.sql
V3__add_user_phone.sql
V4__add_user_index.sql数据库结构就按照:
V1 → V2 → V3 → V4逐步演进。
二、Flyway 的核心原理
Flyway 会维护一张表:
flyway_schema_history其中比较重要的信息有:
假设项目中有:
V1
V2
V3数据库已经有:
V1 success
V2 success那么启动时:
V1 → 已执行 → 跳过
V2 → 已执行 → 跳过
V3 → 没记录 → 执行所以 Flyway 并不是重复执行所有 SQL,而是根据 flyway_schema_history 判断哪些版本没有执行。
这也解释了为什么业务数据被修改或删除后,旧 Migration 不会重新执行。
例如 V2 曾经插入:
INSERT INTO sys_user(id, username)
VALUES (1, 'admin');后来这条数据被删除,Flyway 也不会重新插入,因为:
V2 已经有成功记录Flyway 管的是数据库变更历史,不是当前业务数据。
三、checksum 和 Migration 修改
Flyway 会给每个 Migration 计算一个:
checksum可以理解成 SQL 文件的指纹。
假设 V2 第一次执行时:
checksum = 123456后来你修改了 V2,新的 checksum 变成:
789012启动时 Flyway 发现:
数据库记录:123456
当前文件: 789012就会报:
checksum mismatchSpring Boot 集成 Flyway 时,通常会导致:
Flyway 校验失败
→ Spring Boot 启动失败所以原则很简单:
已经成功执行过的 Versioned Migration 不要修改,有新的数据库变化就新增版本。
例如:
V1
V2
V3
V4一直向后增加。
Migration 命名格式:
V版本号__描述.sql例如:
V3__add_user_phone.sql版本号和描述之间必须使用两个下划线 __。
多人项目可以用时间戳减少版本冲突:
V202610211030__add_device_status.sql四、Migration 执行失败的坑
假设:
V1 成功
V2 失败V1 不会因为 V2 失败而回滚。
并且在 MySQL 中,V2 文件内部也不能认为一定全部回滚。
例如:
ALTER TABLE sys_user ADD COLUMN age INT;
ALTER TABLE sys_user ADD COLUMN phone VARCHAR(20);
ALTER TABLE not_exist_table ADD COLUMN test VARCHAR(20);可能出现:
age 已添加
phone 已添加
第三条失败所以 Migration 执行失败后,不要直接修改 SQL 然后重启。
应该先:
检查数据库实际状态
→ 确认哪些 SQL 已执行
→ 处理已经产生的修改
→ 再重新执行否则可能出现:
Duplicate column五、老项目怎么引入 Flyway
新项目
最简单的方式是项目刚创建时就引入 Flyway:
V1 → V2 → V3 → V4从一开始就完整管理数据库版本。
老项目
老项目已经有很多表和数据,不能重新执行 V1,所以需要:
BaselineBaseline 可以理解为:
告诉 Flyway:当前数据库已经处于某个版本,从后面的版本开始执行。
例如:
spring:
flyway:
baseline-on-migrate: true
baseline-version: 1表示:
当前老数据库已经是 V1那么:
V1 → 不执行
V2 → 执行
V3 → 执行如果:
baseline-version: 2则表示:
当前老数据库已经是 V2那么:
V1 → 不执行
V2 → 不执行
V3 → 执行所以直接记:
baseline-version=N表示当前老数据库已经处于 V N,小于等于版本N 的 Migration 都不会执行。
baseline-on-migrate 一般只在老项目第一次接入 Flyway 时开启。
Baseline 成功、flyway_schema_history 已经建立后,建议关闭。
以后新增:
V2
V3
V4
...正常按 Flyway 版本继续管理即可。
老项目也可以整理一个完整的:
V1__baseline.sql已有数据库 Baseline 到 V1,不执行 V1。
以后创建新的空数据库时,可以正常:
V1 → V2 → V3这样新老数据库最终使用同一套 Flyway 版本体系。
六、总结
Flyway 最核心就是:
Migration
↓
flyway_schema_history
↓
version → 判断执行过没有
checksum → 判断历史文件有没有被修改记住下面几条就够了:
Flyway 管数据库变更历史。
flyway_schema_history记录 Migration 执行情况。没有成功记录的新版本才执行。
已执行 Migration 被修改会导致 checksum mismatch。
已执行的 Versioned Migration 不要修改,继续新增版本。
MySQL Migration 失败后要检查数据库实际状态。
新项目最好一开始就使用 Flyway。
老项目通过 Baseline 接入。
baseline-version=N表示数据库已经处于 VN。baseline-on-migrate一般首次接入时开启,成功后关闭。
