← 中文资源

简体中文版本

用 migra 检测环境间 schema 漂移

用 migra 对比两个在线 Postgres schema,评审生成的 SQL 差异,并把漂移收编回版本化迁移。

阅读英文原文

目标

迁移文件描述的是“应然的历史”,线上 schema 才是事实。每次应急手工打的补丁都会拉开两者的差距,直到预发与生产对列和约束的认知悄然分歧。migra 同时读取两侧目录并打印能弥合差异的 SQL,把看不见的负债变成可评审的 diff,最终落成一份正式迁移文件。

步骤要点

  1. 运行 migra 对比预发与生产两个连接串,得到“把 A 变成 B”的 SQL 差异。
  2. 用 grep 提取 ALTER/CREATE/DROP 逐条分类:出现在生产却不在任何迁移文件里的是手工漂移,只缺于生产的是未应用迁移。
  3. 把确认的漂移改写成幂等的和解迁移(ADD COLUMN IF NOT EXISTS 等),保证在漂移库与干净库上都能执行。
  4. 应用后重跑 migra,diff 行数应降到噪声基线,两侧 schema 与迁移历史一致。
  5. 在 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; }