为什么一步式迁移会破坏发布
滚动发布会同时运行新旧代码。如果迁移删除了旧版本仍在读取的列,重叠期间请求就会失败。扩展-收缩让每个阶段都兼容两个版本。
-- 扩展:可空、向后兼容
ALTER TABLE accounts ADD COLUMN display_name text;
-- 分批回填
UPDATE accounts
SET display_name = name
WHERE display_name IS NULL
AND id IN (SELECT id FROM accounts WHERE display_name IS NULL LIMIT 1000);
步骤
- 扩展 schema:添加可空列、新表或新索引,不删除或重命名现有结构;在支持时使用并发建索引。
- 部署双写或兼容读逻辑,先写新旧字段并以回退方式读取,逐步发布。
- 在有界批次中回填历史数据,监控复制延迟与锁等待,校验行数与约束。
- 回填验证并观察后,把读取切换到新结构,移除回退逻辑。
- 在后续版本中收缩:确认没有实例使用旧结构后,删除旧列/表与兼容代码。
验证
- 新旧应用版本都能通过针对迁移后 schema 的集成测试。
- 行数与约束符合预期。
- 回填期间锁等待与查询延迟在预算内。
- 生产级副本上的备份恢复成功。
回滚
收缩阶段之前,回滚只是代码变更,旧 schema 仍在。收缩之后,回滚需要从备份恢复被删除的结构或执行可逆迁移,因此应等新版本验证充分后再执行破坏性步骤。
决策点
活跃表优先使用在线扩展-收缩;只有确实无法在线执行时才使用维护窗口。回填使用有界批次并监控延迟与锁;单个大事务会增加锁时间与回滚成本。