加 / 删列、建表、改名、加索引、改约束——结构变了,就要有版本和 down。
数据与服务 · 运行与可靠性
数据迁移Migration
迁移是给数据库的一次可追踪、按序、可回滚的「提交」:改结构只写迁移、按序应用、不改已上线历史;破坏性改名用「先扩后缩」分步零停机完成。
试一遍:按序应用迁移,看 users 表结构怎么变
点「应用下一条」按 001→002→003 推进,users 表的列会实时变化;003 是破坏性改名,会展开「扩展 → 迁移 → 收缩」三步;点「回滚(down)」逐步还原。结构变化长在表上,不只是底下文案。
id主键nameemail
每一步结构都对正在跑的代码可读:加列不影响旧代码,删列放在最后。
- 001新增
avatar_url列(可空)扩展→ 下一条 - 002回填
avatar_url数据· 待应用 - 003把
name改名display_name破坏性·先扩后缩- 扩展新增 display_name、拷贝 name· 待应用
- 迁移双写 + 读切到 display_name· 待应用
- 收缩删除 name· 待应用
users 表 · 3 列,尚未应用迁移users 表当前 3 列。点「应用下一条」按 001→002→003 顺序推进;003 是破坏性改名,会展开「扩展 / 迁移 / 收缩」三步。每一步都能用「回滚(down)」恢复到上一版结构——成对写 up / down 的原因就在这里。
迁移是什么:给数据库的一次提交
面板里已经见过,这里只命名:按序、版本化、可回滚、不改历史。
- 按序 + 版本化
001、002、003 像提交一样排成时间线;每个环境都按同一顺序追到同一形状。
- 可回滚(up / down)
每条迁移写 up 应用的同时写 down 撤销;面板里点「回滚」就看到结构退回。
- 不改已上线历史
已应用的迁移被锁住;要再改就写一条新迁移,而不是回去改旧文件——否则环境之间会不一致。
- 破坏性改动先扩后缩
加列、双写切读、最后删旧列,分成多次部署,避免锁表和断读。
什么时候靠迁移
凡是改生产数据库结构的操作都走迁移;只改业务数据用数据脚本或后台任务。
修一条订单状态、清脏数据——是数据变更不是结构变更,用幂等脚本或后台任务。
怎么用才不出错
从写迁移到上生产的最短路径,加上 staging 和 CI 两道关。
- 写迁移:成对写 up / down,破坏性改名拆成扩展、迁移、收缩多条。
- 本地跑通后,先在 staging 用近似生产的数据验证耗时、锁和兼容性。
- CI 里跑迁移,失败立刻红灯;migrate-on-deploy 让部署和应用代码同步推进。
- 出错用 down 回滚到上一版结构,或写一条新迁移从断点继续——不手工改 prod 表。
同一任务的正反例
同一个「把 name 改名 display_name」,正例写新迁移并先扩后缩,反例改历史或一步 RENAME。
先加 display_name 并拷贝 name,部署双写、切读,确认稳定后再删 name。每一步都能单独回滚, 正在跑的代码始终能读到其中一列。
差异:历史不变,改动可回滚,全程零停机。直接编辑 prod 已经跑过的迁移文件,环境之间立刻不一致;一条 RENAME 在旧代码还在读 name 的瞬间就断读,而且没有可回滚的中间态。
差异:破坏不可逆历史,且把删 / 改一步做完,没有退路。快速自测
生产表里一个有数据的列要改名,最安全的顺序是哪一种?
继续查证
术语的技术定义和行为以这些一手或权威资料为准。
下一步学
和本知识点经常一起出现的概念。