我们经常使用flyway的都知道,Flyway 通过 校验和(Checksum) 机制来检测脚本内容的变化,接下来我们来了解一下具体的判断逻辑和操作方法
1. 校验和(Checksum)机制
原理:
Flyway 会对每个迁移脚本的内容计算一个唯一的 校验和(哈希值),并将该值与元数据表flyway_schema_history
中的记录进行比对。校验流程:
当应用启动并执行 Flyway 迁移时:扫描所有迁移脚本(包括
V
和R
脚本)。计算每个脚本的校验和(基于文件内容)。
与元数据表中记录的校验和进行对比:
匹配:脚本未变化,跳过执行。
不匹配:触发不同行为(取决于脚本类型)。
每个SQL脚本都会经flyway校验之后生成一个Checksum值。
2. 检测 V 脚本是否被修改
规则:
如果已执行的V
脚本内容发生 任何修改(包括空格、注释、字符大小写等),其校验和会发生变化。结果:
Flyway 会抛出校验错误,终止迁移流程,并提示类似以下错误:
Validate failed: Migration checksum mismatch for version 1.2.0
-> Applied to database : 1234567890
-> Resolved locally : 0987654321
修复方式:
禁止直接修改已发布的
V
脚本(生产环境需严格遵循此规则)。如果需要修复问题,应创建新的
V
脚本(如V1.2.1__Fix_User_Table.sql
)。如果开发环境需强制覆盖,可手动清理元数据表(不推荐生产环境使用)。
3. 检测 R 脚本是否变化
规则:
R
脚本的校验和变化会被 Flyway 识别,但不会报错。结果:
Flyway 会重新执行修改后的
R
脚本,并更新元数据表中的校验和记录。执行日志会提示:
Successfully applied migration (repeated): R__Update_Product_View
注意事项:
确保
R
脚本是 幂等 的(多次执行结果一致)。修改
R
脚本后,Flyway 会按文件名顺序重新执行所有R
脚本(即使只有部分脚本被修改)。
4. 手动检查校验和
方式 1:查询元数据表
直接查询 flyway_schema_history
表,查看已执行脚本的校验和:
SELECT script, checksum FROM flyway_schema_history ORDER BY installed_rank;
输出示例:
script | checksum |
---|---|
V1.0__Create_Table.sql | 123456789 |
R__Update_View.sql | 987654321 |
方式 2:Flyway 命令行工具
使用 flyway info
命令查看校验和对比:
flyway info
输出示例:
+-----------+---------+---------------------+------+---------------------+---------+----------+
| Category | Version | Description | Type | Installed On | State | Undoable |
+-----------+---------+---------------------+------+---------------------+---------+----------+
| Versioned | 1.0 | Create Table | SQL | 2023-10-01 10:00:00 | Success | No |
| Repeatable| | Update View | SQL | 2023-10-01 10:00:00 | Outdated| No |
+-----------+---------+---------------------+------+---------------------+---------+----------+
Outdated
状态表示R
脚本的本地校验和与数据库记录不一致。
5. 校验和计算原理
Flyway 使用 CRC32 算法 计算脚本内容的校验和,具体规则:
移除 SQL 中的 注释 和 空白符(默认配置下)。
按行分割脚本内容。
逐行计算哈希值并合并为最终校验和。
6. 常见场景与解决方案
场景 1:V 脚本被意外修改
现象:应用启动时报错
Migration checksum mismatch
。解决:
生产环境:回滚代码到原始版本,或创建新版本脚本修复问题。
开发环境:手动修复元数据表中的校验和(仅用于临时调试):
UPDATE flyway_schema_history
SET checksum = <新校验和>
WHERE script = 'V1.0__Create_Table.sql';
场景 2:R 脚本修改后未生效
现象:修改后的
R
脚本未重新执行。排查:
检查文件名是否符合
R__Description.sql
格式。确认脚本路径已包含在
spring.flyway.locations
配置中。检查是否关闭了校验(
validate-on-migrate: false
)。
7. 最佳实践
V 脚本不可变性:
提交到代码仓库的
V
脚本禁止修改,必须通过新增版本来修复问题。
R 脚本幂等性:
使用
CREATE OR REPLACE
代替CREATE
定义视图或存储过程。通过
DELETE
+INSERT
而非直接UPDATE
更新数据。
校验配置:
生产环境始终启用
validate-on-migrate: true
。开发环境可启用
flyway.validate-migration-naming: true
强制命名规范检查。
通过校验和机制,Flyway 确保了数据库迁移的 可追溯性 和 一致性。