返回知识库

数据与服务 · 运行与可靠性

数据迁移Migration

迁移是给数据库的一次可追踪、按序、可回滚的「提交」:改结构只写迁移、按序应用、不改已上线历史;破坏性改名用「先扩后缩」分步零停机完成。

试一遍:按序应用迁移,看 users 表结构怎么变

点「应用下一条」按 001→002→003 推进,users 表的列会实时变化;003 是破坏性改名,会展开「扩展 → 迁移 → 收缩」三步;点「回滚(down)」逐步还原。结构变化长在表上,不只是底下文案。

users 表 · 当前结构3
  • id主键
  • name
  • email

每一步结构都对正在跑的代码可读:加列不影响旧代码,删列放在最后。

  1. 001新增 avatar_url 列(可空)扩展→ 下一条
  2. 002回填 avatar_url数据· 待应用
  3. 003name 改名 display_name破坏性·先扩后缩
    1. 扩展新增 display_name、拷贝 name· 待应用
    2. 迁移双写 + 读切到 display_name· 待应用
    3. 收缩删除 name· 待应用

users 表 · 3 列,尚未应用迁移users 表当前 3 列。点「应用下一条」按 001→002→003 顺序推进;003 是破坏性改名,会展开「扩展 / 迁移 / 收缩」三步。每一步都能用「回滚(down)」恢复到上一版结构——成对写 up / down 的原因就在这里。

迁移是什么:给数据库的一次提交

面板里已经见过,这里只命名:按序、版本化、可回滚、不改历史。

  1. 按序 + 版本化

    001、002、003 像提交一样排成时间线;每个环境都按同一顺序追到同一形状。

  2. 可回滚(up / down)

    每条迁移写 up 应用的同时写 down 撤销;面板里点「回滚」就看到结构退回。

  3. 不改已上线历史

    已应用的迁移被锁住;要再改就写一条新迁移,而不是回去改旧文件——否则环境之间会不一致。

  4. 破坏性改动先扩后缩

    加列、双写切读、最后删旧列,分成多次部署,避免锁表和断读。

什么时候靠迁移

凡是改生产数据库结构的操作都走迁移;只改业务数据用数据脚本或后台任务。

走迁移

加 / 删列、建表、改名、加索引、改约束——结构变了,就要有版本和 down。

不走迁移

修一条订单状态、清脏数据——是数据变更不是结构变更,用幂等脚本或后台任务。

怎么用才不出错

从写迁移到上生产的最短路径,加上 staging 和 CI 两道关。

  • 写迁移:成对写 up / down,破坏性改名拆成扩展、迁移、收缩多条。
  • 本地跑通后,先在 staging 用近似生产的数据验证耗时、锁和兼容性。
  • CI 里跑迁移,失败立刻红灯;migrate-on-deploy 让部署和应用代码同步推进。
  • 出错用 down 回滚到上一版结构,或写一条新迁移从断点继续——不手工改 prod 表。

同一任务的正反例

同一个「把 name 改名 display_name」,正例写新迁移并先扩后缩,反例改历史或一步 RENAME。

正例写一条新迁移 003,用「先扩后缩」改名

先加 display_name 并拷贝 name,部署双写、切读,确认稳定后再删 name。每一步都能单独回滚, 正在跑的代码始终能读到其中一列。

差异:历史不变,改动可回滚,全程零停机。
反例回去改已上线的 001,或一条 ALTER 直接 RENAME

直接编辑 prod 已经跑过的迁移文件,环境之间立刻不一致;一条 RENAME 在旧代码还在读 name 的瞬间就断读,而且没有可回滚的中间态。

差异:破坏不可逆历史,且把删 / 改一步做完,没有退路。

快速自测

生产表里一个有数据的列要改名,最安全的顺序是哪一种?

继续查证

术语的技术定义和行为以这些一手或权威资料为准。

下一步学

和本知识点经常一起出现的概念。