多应用多实例共享同一Schema时使用Flyway进行迁移的可行性问询
Flyway相关问题解答
预期是否符合Flyway实际运行逻辑
不符合。
Flyway本身没有「首个实例添加Pending状态记录、其余实例感知后跳过」的设计逻辑,它的互斥机制是基于数据库锁实现的:执行迁移前,Flyway会尝试对flyway_schema_history表加数据库级排他锁,第一个启动的实例拿到锁后会执行迁移逻辑,其余实例会阻塞等待锁释放,而不是直接跳过。等第一个实例完成迁移、释放锁之后,后续实例拿到锁会先校验历史表的当前版本,如果已经是最新版本,才会直接跳过迁移步骤,不会重复执行。
另外Flyway的历史表中不存在Pending状态,目前官方支持的状态只有SUCCESS、FAILED、OUT_OF_ORDER、BASELINE等,迁移脚本执行成功后才会写入SUCCESS状态的记录,执行失败会写入FAILED状态的记录,不会提前写入待执行标记。
该机制是否可信赖
Flyway默认的锁机制是生产级可靠的,只要你的数据库本身的锁机制运行正常(比如使用支持行级锁的存储引擎、没有极端的锁超时/数据库异常宕机导致锁未释放的情况),完全可以信赖,不会出现多实例重复执行迁移脚本的问题。
多应用共用数据库场景的业界通用方案
你们当前是两款不同应用共用同一数据库的场景,不推荐直接把Flyway迁移逻辑耦合在应用启动流程中,业界常用的处理方案有以下几种:
- 首选方案:抽离独立的迁移执行流程,不在业务应用启动时执行Flyway。比如在CI/CD发布流程中增加独立的Flyway执行阶段,应用发布前先由流水线统一执行所有迁移脚本,所有业务应用都不内置Flyway执行逻辑,从根源上避免多应用、多实例的迁移冲突,这也是目前生产环境最常用的方案。
- 如果一定要保留应用启动时执行迁移的逻辑,需要给两款不同应用配置独立的Flyway历史表,通过
flyway.schema_history_table参数分别指定不同的表名,避免两个应用的迁移脚本版本号、执行记录互相干扰,同个应用的多实例依靠Flyway默认的锁机制即可保证不重复执行。 - 如果必须让两款应用共用同一张Flyway历史表,需要提前严格约定版本号规则,比如应用A的所有迁移脚本版本号使用
1.x.x前缀,应用B使用2.x.x前缀,避免版本号冲突,同时仍然建议尽量用独立流程统一执行迁移,不要分散在应用启动阶段操作。
内容的提问来源于stack exchange,提问作者dj_segfault
相关产品推荐
相关产品推荐

