凌晨三点删库惊魂?FlyWay让我从此睡上安稳觉!直接涨薪30%
🌟 开篇:为什么全栈工程师都在偷偷用FlyWay?
数据库版本管理就像给数据库办身份证——没有它,你的开发团队迟早会在凌晨三点哭着找DBA!FlyWay用SQL脚本实现版本控制,比传统方式快得像闪电侠吃辣条,支持Java/Go/Python等8+语言,GitHub收获17k+星证明它就是开发界的"万金油"。
🌟环境支持
Supported databases
Aurora MySQL, Aurora PostgreSQL, Azure Synapse, Clickhouse, CockroachDB, Databricks, DB2, Derby, Firebird, Google BigQuery, Google Cloud Spanner, H2, HSQLDB, Informix, MariaDB, MongoDB, MySQL, Oracle, Percona XtraDB Cluster, PostgreSQL, Redshift, SAP HANA (Including SAP HANA Cloud), SingleStoreDB, Snowflake, SQLite, SQL Server, Sybase ASE, TiDB, TimescaleDB, YugabyteDB
Third party plugins
SBT, Ant, Spring Boot, Grails, Play!, DropWizard, Grunt, Griffon, Ninja, ...
🌟真实的生产案例FlyWay
一般来说,后台开发会分为dev(开发环境),test(测试环境),uat(用户验收测试环境),prod(生产环境)。为了保持所有环境的数据库脚本一致性,在项目上线前,我们会按照dev-test-uat-prod的顺序依次手动执行存量脚本。
但是最近我们的业务系统对接了100多个工厂,因此生产环境扩充了100多套数据库,为了保持所有工厂的数据库脚本一致性,各个环境手动更新脚本显然不现实,这个时候就要用到数据库脚本迁移维护工具了,比如flyway和Liquibase,本文只介绍flyway,引入flyway的springboot工程的环境配置如下
项目依赖如下:
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>6.4.1</version>
</dependency>
引入依赖后的flyway工程配置文件如下:
- application.yaml:配置profile激活场景
- application-dev.yaml:配置了dev环境数据源
- application-test.yaml:配置了test环境数据源
- application-uat.yaml:配置了uat环境数据源
- application-prod-factory01.yaml:配置了factory01生产环境数据源
- application-prod-factory02.yaml:配置了factory02生产环境数据源
- application-prod-factory03.yaml:配置了factory03生产环境数据源
- application-prod-factory04.yaml:配置了factory04生产环境数据源
- application-prod-factory05.yaml:配置了factory05生产环境数据源
- application-prod-factory06.yaml:配置了factory06生产环境数据源
- ...
- application-prod-factory110.yaml:配置了factory110生产环境数据源
例如application-dev.yaml:
spring:
application:
name: flyway-db
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/iot_db_user?useUnicode=true&useSSL=false&characterEncoding=utf-8
username: balabala
password: balabala
# 模拟配置中心的配置
flywaydb:
url: ${spring.datasource.url}
username: username
password: password
# 以下配置可以配置在 当前项目中
# 配置是否启动项目的时候,执行 repair 和 migrate 方法,用于自测;一般不需要配置
# startEnable: false
# 如果有自定义需求,可以通过 locations 配置 SQL 脚本的存放目录,支持多个目录,用 “,” 隔开
# locations: db/migration/V1_0_0,db/migration/V2_0_0
利用profiles参数实现不同环境配置切换,比川剧变脸还丝滑
🛠️ 核心原理解剖(附带灵魂手绘)
想象你的数据库是乐高城堡,FlyWay就是那个强迫症建筑总监:
1️⃣ 扫描springboot工程resource资源下db/migration目录下的SQL文件
2️⃣ 自动创建元数据表flyway_schema_history
3️⃣ 按版本号严格排序执行,依据flyway_schema_history字段version
4️⃣ 校验文件哈希值防止篡改,依据flyway_schema_history字段checksum
整个过程比处女座整理衣柜还要严谨!
🚧 命名强迫症
文件名必须遵守V1.2.3__Description.sql格式,少个下划线都给你摆脸色!
在迁移目录classpath:/db/migration 下创建迁移文件,文件命名以V开头,以.sql结尾,数字为版本号,迁移文件版本号后面是两个连续的下划线。
🚧 迁移文件举例
第一个迁移文件V1__Initial_Setup.sql
create table person(
id serial primary key,
name text,
date date,
sex bool,
blob blob,
clob clob
);
第二个迁移文件V2__First_Changes.sql
insert into person(name,date,sex,blob,clob) values('aaa','2020-01-01','f','aaa','bbb');
🚧执行迁移。普通java 程序执行以下代码进行迁移:
Flyway flyway = Flyway.configure().dataSource(url, user, password).load();
flyway.migrate();
如果是springboot 项目,由参数 spring.flyway.enabled 来控制 flyway 的开启,flyway 默认启用,在项目启动部署后就会自动加载。
spring.flyway.enabled=true
应用每次迁移时,架构历史记录表都会相应地更新:
🚀 六大碾压级优势
- SQL原生支持:告别XML/YAML的啰嗦语法(Liquibase:你直接报我身份证号得了)
- 秒级执行:千级脚本可在3分钟内完成迁移(实测比同行快40%)
- 多数据库制霸:从MySQL到Snowflake通吃25+数据库
- DevOps友好:完美集成Spring Boot/K8s/Jenkins
- 安全回滚:企业版提供undo migration功能(免费版建议自己写回滚脚本)
- 社区活跃度MAX:Stack Overflow问题5分钟必答
💣 生产环境保命三式
❗ 永远先在预发环境测试
❗ 禁用clean命令(除非想体验删库到跑路)
❗ 使用flyway.validateOnMigrate=true
❗ ❗ ❗ 老司机避坑指南
下面是作者夙夜SEngineer含泪整理的FlyWay最佳实践
情况一:误删了原脚本怎么办
在开发阶段,已经写了V1_1__create.sql,也已经 migrate,但是之后发现这个脚本没用或者不允许刷脚本(比如是定制化的业务数据),要删掉,但是删除掉后续再执行migrate时,发现会报错
ERROR: Validate failed: Detected applied migration not resolved locally: 5.5
flyway是不支持降级的,所以解决办法有如下两种:
方案一:即便你发现这个sql没用,你不应该删除,你应该补充一个sql去弥补之前的sql逻辑,虽然强烈推荐这样做,但是存在你无法弥补的逻辑比如下述被误删的sql:由于是批量更新字段脚本,这种极端的情况你无法还原老的环境数据库中table.colume原来对应的值,因此这种情况下弥补是没有意义的
-- 老的脚本
update table set colume = 'value'
方案二:在数据库中,找到已经执行了历史脚本环境的flyway_schema_history表,将你之前误删掉的sql文件对应的记录删除掉(可选:同时再新建一份完全弥补的sql视为新的记录),重新执行migrate。此时flyway会帮我们回退脚本
虽然这些老的环境数据库已经执行了老的sql,但一般都是开发或者测试环境,问题不大,保证了以后的新的环境不再出现这种的问题即可
情况二:原脚本修改怎么办
如果一个sql文件,已经migrate,之后由于某种原因(原因比较复杂如老环境数据库不报错但是新环境数据库报错),则必须要对历史sql进行修改以兼容以后的新环境数据库,修改之后再migrate发现过去老的环境数据库必然会报错:
ERROR: Validate failed: Migration checksum mismatch for migration 4.1
-> Applied to database: 707727666
-> Resolved locally: -1890253217
这里的报错是因为checksum值和之前的不一样了(当文件修改过后,生成的校验码会改变),flyway就是通过这个值来觉得这个文件是否已经执行了。flyway_schema_history表结构如下:
CREATE TABLE "flyway_schema_history" (
"installed_rank" INTEGER NOT NULL,
"version" VARCHAR(50) NULL DEFAULT NULL,
"description" VARCHAR(200) NOT NULL,
"type" VARCHAR(20) NOT NULL,
"script" VARCHAR(1000) NOT NULL,
"checksum" INTEGER NULL DEFAULT NULL,
"installed_by" VARCHAR(100) NOT NULL,
"installed_on" TIMESTAMP NOT NULL DEFAULT now(),
"execution_time" INTEGER NOT NULL,
"success" BOOLEAN NOT NULL,
PRIMARY KEY ("installed_rank")
)
;
COMMENT ON COLUMN "flyway_schema_history"."installed_rank" IS '';
COMMENT ON COLUMN "flyway_schema_history"."version" IS '';
COMMENT ON COLUMN "flyway_schema_history"."description" IS '';
COMMENT ON COLUMN "flyway_schema_history"."type" IS '';
COMMENT ON COLUMN "flyway_schema_history"."script" IS '';
COMMENT ON COLUMN "flyway_schema_history"."checksum" IS '';
COMMENT ON COLUMN "flyway_schema_history"."installed_by" IS '';
COMMENT ON COLUMN "flyway_schema_history"."installed_on" IS '';
COMMENT ON COLUMN "flyway_schema_history"."execution_time" IS '';
COMMENT ON COLUMN "flyway_schema_history"."success" IS '';
所以解决方案是:
首先必要的修改脚本sql
然后注释掉其他老的环境配置,只对新的特需环境数据库执行修改后的sql脚本,这时会在新库的history中的生成记录,记录中包含新的校验码
然后修正报错的环境数据库中的错误的sql文件对应的校验码为新的校验码
最后放开老的环境数据库,对所有的老的环境数据库重新执行migrate校验发现没问题了
注意你需要将所有已经出问题的环境数据库history对应的错误记录的校验码都改为新的校验码
情况三:紧急给生产环境数据库表添加了索引但没有刷脚本怎么办
紧急给生产环境数据库表添加了索引,但是没有走测试脚本维护,那么这种有两种解决方案:
- 方案1. 先删除生产索引,再刷一遍生产脚本,否则脚本执行出错提示冲突
- 方案2. 复制测试环境的flyway_schema_history中的该条索引修改记录,导入到生产环境数据库中的flyway_schema_history,则再刷一遍脚本的时候会跳过该条索引脚本
INSERT INTO "flyway_schema_history" ("installed_rank", "version", "description", "type", "script", "checksum", "installed_by", "installed_on", "execution_time", "success") VALUES (158, '20241225.001', 'add-index-message', 'SQL', 'V20241225.001__add-index-message.sql', 1549527570, 'les', '2024-12-30 10:20:15.761868', 58, 'true');
推荐方案2,因为生产数据库数据百万千万级别,删除索引之后再重建索引特别耗时
🏆 终极大比拼:FlyWay vs Liquibase
维度 | FlyWay | Liquibase |
---|---|---|
学习曲线 | 幼儿园滑梯 | 大学微积分 |
执行速度 | 博尔特短跑 | 老奶奶过马路 |
脚本格式 | 原生SQL | XML/YAML |
社区支持 | Stack Overflow海量解答 | 官方文档即迷宫 |
扩展能力 | 插件市场花样百出 | 官方扩展需要买门票 |
2025年,flyway最新支持了Redshift和BigQuery,云原生适配度直接拉满!团队正在研发AI智能迁移建议功能,未来可能帮你自动写回滚脚本(DBA们终于可以放心睡大觉了)。
Reference:
https://github.com/flyway/flyway
https://documentation.red-gate.com/flyway/why-database-migrations
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~