目标
迁移文件描述的是“应然的历史”,线上 schema 才是事实。每次应急手工打的补丁都会拉开两者的差距,直到预发与生产对列和约束的认知悄然分歧。migra 同时读取两侧目录并打印能弥合差异的 SQL,把看不见的负债变成可评审的 diff,最终落成一份正式迁移文件。
步骤要点
- 运行 migra 对比预发与生产两个连接串,得到“把 A 变成 B”的 SQL 差异。
- 用 grep 提取 ALTER/CREATE/DROP 逐条分类:出现在生产却不在任何迁移文件里的是手工漂移,只缺于生产的是未应用迁移。
- 把确认的漂移改写成幂等的和解迁移(ADD COLUMN IF NOT EXISTS 等),保证在漂移库与干净库上都能执行。
- 应用后重跑 migra,diff 行数应降到噪声基线,两侧 schema 与迁移历史一致。
- 在 CI 里加漂移门禁:diff 非空即失败,让下一次手工热修第二天早上就响亮报错。
排错提示
diff 混入扩展与系统对象噪声时,用 schema 选项限定自有 schema,并把监控工具建的对象隔离进专用 schema;只有权限漂移而无结构漂移时 migra 看不见,需另行 dump ACL 或用 IaC 审查角色;策略上不允许直连生产时,可先快照到临时克隆再对比——migra 本身只读目录、绝不写入。
适用边界
migra 输出是方向性 SQL 而非迁移方案,应用前必须人工评审编辑;它只比结构不比数据,种子行的分歧对它不可见。
代码示例
# What SQL would make staging equal production?
migra "$STAGING_URL" "$PROD_URL"
# Keep the gate green
migra "$CI_STAGING_URL" "$PROD_URL" > drift.sql || true
test ! -s drift.sql || { cat drift.sql; exit 1; }