Appearance
数据库变更怎么配合 CI/CD:表结构发布、兼容性和回滚思路
很多团队的应用发布已经自动化了,但数据库变更仍然靠手工执行脚本。
真正危险的地方往往也在这里。
先说结论
数据库变更不应该被看成“应用上线前顺手执行一条 SQL”,而应该被当成发布链路的一部分。
更稳的思路通常是:
- 先做向后兼容的表结构变更
- 再发布应用代码
- 最后再做清理或强约束收口
一、为什么数据库变更最容易把发布搞炸
因为它有几个天然特点:
- 一旦执行,影响范围大
- 部分 DDL 不容易回退
- 新旧版本可能共享同一张表
二、我更推荐的三阶段做法
第一阶段:先扩展,不破坏旧逻辑
例如:
- 新增字段
- 新增索引
- 新增新表
第二阶段:发布应用代码
让新代码逐步开始使用新结构。
第三阶段:收口清理
确认新逻辑稳定后,再做:
- 删除旧字段
- 取消兼容分支
- 增加强约束
三、为什么“改表 + 发版”不适合一把梭
常见危险动作包括:
- 上线前先删旧字段
- 一次性把字段类型直接改死
- 还没回填历史数据就让新代码强依赖
四、CI/CD 里数据库变更应该放在哪
更合理的理解是:
- 数据库脚本也是制品的一部分
但它不一定必须和应用一起“自动直接执行到生产”。
更常见的做法是:
- 流水线校验 SQL 文件规范
- 在测试环境自动执行
- 在生产环境通过审批后执行
五、什么时候要特别小心
1. 大表加索引
2. 字段类型变更
3. 数据回填
如果需要把历史数据补齐,通常不能直接在高峰期一次性跑完。
六、一个常见案例
假设订单表要从:
status
扩展为:
statusstatus_detail
更稳的方式通常是:
- 先新增新字段
- 新版本代码双写新旧字段
- 历史数据逐步回填
- 稳定后再决定是否清理旧逻辑
七、回滚为什么常常卡在数据库这里
应用代码回滚比较直接,但数据库未必。
例如:
- 新版本写入了旧版本无法识别的数据
- 新版本删除了旧字段
- 新版本引入了强约束
八、和 Java 团队更贴近的落地建议
1. SQL 脚本进仓库
2. 变更脚本可审查
3. 测试环境先验证
4. 生产高风险变更保留人工确认
一句话总结
真正稳定的 CI/CD,不只是能自动发包,还要能把表结构兼容性、数据迁移和回滚路径一起纳入发布设计。