数据库迁移审查 Prompt:安全变更模板

12 个迁移审查 Prompt,专抓锁表的 ALTER、backfill race 和悄悄掉列,覆盖 Postgres / MySQL / SQLite,已在 Opus 4.7 与 GPT-5.5 上验证。

大多数”迁移把表锁住了”的事故都有同一个根因:审查的人只看了 diff、不知道行数和锁类型,就敲下”看着行”。Postgres 社区有个真实例子:一条本该三秒完成的 ALTER TABLE ... ADD COLUMN 排在一个长跑的分析查询后面,所有后续查询又排在这个等待中的 ACCESS EXCLUSIVE 锁后面,连接池里约 2000 个连接被耗尽——一条三秒的语句拖出了 45 分钟的故障。

好的迁移审查 Prompt 就是来挡这种事的。它强制模型说清楚表大小档位、这条语句实际拿的是哪种锁、回滚配方,并硬性禁止把 schema + 数据 + 行为变更塞进一个迁移。下面是 12 个可直接复制的模板,外加一张 AI 审查者真正用得上的锁参考表。

TL;DR

  • 把迁移 diff 贴进模板 1(“迁移安全 triage”),一轮就能拿到 GREEN / YELLOW / RED 判定。
  • 永远先把行数给模型——所有安全估算都依赖它。
  • 审查推理用 Claude Opus 4.7 或 GPT-5.5(截至 2026 年 6 月,两者 SWE-bench Pro 都在 58% 以上),它们能抓到小模型漏掉的部署顺序风险。
  • 不可妥协的规则:Postgres 建索引用 CONCURRENTLY、任何 DDL 前 SET lock_timeout、backfill 分批、回滚和迁移放同一个 PR。

适合哪些人

任何要给迁移签字的人:DBA、后端 lead、上线前的创业团队,以及做 forward-only 发布验证的值班工程师。

别用这套 Prompt 审 greenfield schema 设计(那是建模问题,不是迁移审查);也别在确实不知道表行数的时候用——先把那个数字拿到手。

AI 审查者必须看到的锁参考表

迁移审查的质量,取决于它是否清楚哪条语句拿哪种锁。把下面这张表贴进模型上下文,它就不会再含糊地说”可能有点慢”。下表锁行为以 Postgres 14+ 为准,截至 2026 年 6 月。

操作拿的锁阻塞读?阻塞写?安全做法
ADD COLUMN(无 volatile 默认值)ACCESS EXCLUSIVE,仅改元数据否(瞬时)短暂PG 11 起安全,仍要 SET lock_timeout
ADD COLUMN ... DEFAULT <常量>ACCESS EXCLUSIVE,仅改元数据短暂常量默认值存进 catalog,不重写表
大表 ADD COLUMN ... NOT NULL重写 / 长锁先加可空列,backfill,CHECK ... NOT VALIDVALIDATE
CREATE INDEXSHARECREATE INDEX CONCURRENTLYSHARE UPDATE EXCLUSIVE
ADD UNIQUE / PRIMARY KEYACCESS EXCLUSIVECONCURRENTLY 建索引,再 ADD CONSTRAINT ... USING INDEX
ALTER COLUMN TYPE重写用新列做 expand-contract
DROP COLUMNACCESS EXCLUSIVE,仅改元数据短暂安全,但要确认没有线上代码还在读它

每个 Postgres 迁移上,模型都该强制两条规则:一是设 lock_timeout(5 秒是常用默认值),让 DDL 拿不到锁就快速失败、而不是把所有流量堵在后面;二是绝不让长 DDL 干等——一个等待中的 ACCESS EXCLUSIVE 锁会阻塞它之后到达的所有冲突查询,这正是一条快语句拖出长故障的机制。

12 个可直接复制的 Prompt 模板

每个模板都用 [方括号] 占位符。先把上面那张锁表贴进同一个对话,模型才会基于真实锁语义推理。做多迁移或部署顺序分析时,用 1M token 上下文的模型(Opus 4.7、Sonnet 4.6、Gemini 3.1 Pro,截至 2026 年 6 月均为 1M),可以把整个 diff 加调用方代码一次性塞进一条消息。

1. 迁移安全 triage

Review this migration: [migration SQL]. Output:
(1) Lock duration estimate based on table size class (S < 100k, M < 10M, L > 10M rows),
(2) Concurrent-deploy compatibility — does the old code break against the new schema?
(3) Required backfill,
(4) Rollback recipe,
(5) GREEN / YELLOW / RED verdict with the single biggest risk.

替换: 迁移 SQL。

2. 大表加 NOT NULL

Plan to add NOT NULL to a table with [rowCount] rows. Steps:
(1) Add a nullable column,
(2) Backfill in batches of N with idle waits,
(3) Verify zero NULLs,
(4) ADD CONSTRAINT ... CHECK (col IS NOT NULL) NOT VALID,
(5) VALIDATE CONSTRAINT (Postgres),
(6) optionally SET NOT NULL once validated.
Specify batch size and a downtime estimate.

替换: rowCount

3. DROP / RENAME 风险检查

This migration DROPs / RENAMEs `[columnOrTable]`. List which application code
reads / writes it (file:line). Compute the deploy-order risk: if old code reads
it after the new schema applies, you have downtime. Output a deploy-order plan,
or "BLOCK — old code still active".

替换: columnOrTable

4. 大表加索引

Plan to create an index on a [rowCount]-row table. Decide:
(1) CREATE INDEX CONCURRENTLY (Postgres) or gh-ost / pt-online-schema-change (MySQL)?
(2) Estimated build time and lock impact,
(3) Disk space needed,
(4) How to detect a duplicate-blocked invalid index afterward,
(5) Plan B if cancelled mid-build (drop the INVALID index, retry).

替换: rowCount

5. Backfill 批处理

Backfill [nRows] rows of column `[col]`. Plan:
(1) Batch size and sleep between batches,
(2) Idempotency (resume on failure from last committed PK),
(3) Progress tracking,
(4) Replica lag monitoring and a throttle threshold,
(5) Abort criteria.
Output as a runnable script outline.

替换: nRowscol

6. forward-only 验证

This migration is forward-only (no DOWN). Verify it is recoverable forward:
(1) If applied partially, can the next deploy re-run it safely (idempotent)?
(2) Is the new schema observable by old code (NULLABLE / DEFAULT)?
(3) Is the behaviour change feature-flag-protected?
Output GO / NO-GO with the blocking item.

7. 回滚配方

Write a rollback recipe for this migration:
(1) Revert SQL (or compensating writes),
(2) Data restore strategy if rows were transformed in place,
(3) Order relative to the application revert,
(4) Deadline for safe rollback (after which data drift makes it unsafe).

8. 锁感知 DML 改写

This UPDATE will lock [tableName] for a long time: [sql].
Rewrite it as batched UPDATEs with a lock-friendly WHERE clause, using
keyset (cursor) iteration over the primary key. Show the rewritten SQL plus a
runner skeleton that commits each batch and sleeps between them.

替换: tableNamesql

9. 并发迁移协调

Two migrations land this week: [migA] and [migB]. Check:
(1) Do they touch the same table?
(2) Will they serialize on the same lock?
(3) Is the deploy order specified?
(4) Are both idempotent if one fails mid-deploy?
Output a coordination plan.

替换: migAmigB

10. 迁移测试计划

Generate a test plan for this migration:
(1) Run on a copy of prod-shaped data (not seed fixtures),
(2) Time it under realistic concurrency,
(3) Assert the post-state matches expected (row counts, constraints, indexes valid),
(4) Run app smoke tests against the migrated DB.
Output a runnable checklist.

11. RLS / 策略迁移审查

This migration adds / changes row-level security policies on `[table]`. Verify:
(1) Existing queries still authorise correctly (no accidental lockout),
(2) Service-role / bypass queries are unaffected,
(3) Policy combination — PERMISSIVE (OR) vs RESTRICTIVE (AND),
(4) Tests cover authed, anon, and cross-tenant paths.

替换: table

12. 迁移事故复盘

A migration caused this incident: [incidentSummary]. Write a brief post-mortem:
(1) What lock / write pattern caused the outage,
(2) Why review didn't catch it,
(3) One process change (e.g., require row-count in the PR description),
(4) One automated check to add (e.g., a linter that flags ADD COLUMN NOT NULL).
200 words max.

替换: incidentSummary

迁移审查该用哪个模型

迁移审查是推理任务,不是生成任务:模型得追踪部署顺序、锁之间的相互作用,以及哪些代码会读到被改的列。截至 2026 年 6 月,最强的两个选择是 Claude Opus 4.7(SWE-bench Pro 64.3%)和 GPT-5.5(58.6%),它们的推理足以抓出某个老 replica 还在读的改名操作。Sonnet 4.6 和 Gemini 3.1 Pro 更便宜,做单表 triage 也够用。四者都是 1M token 上下文,可以把迁移 diff、锁表和相关应用代码一起贴进去——而这正是抓住并发部署风险的关键。

如果你在终端里跑审查,可以看Claude Code 执行 Prompt,把这些模板接进一个能自己读 diff 和调用方代码的 agent。

容易踩的坑

  • 一条语句给大表加 NOT NULL(整表重写、长锁)。
  • 改列名时老代码还在读它——部署瞬间就停服。
  • 热表上 CREATE INDEX 没加 CONCURRENTLY
  • 没设 lock_timeout,等待中的 DDL 把所有流量堵在后面。
  • 没回滚配方,首次失败就变成长时间故障。
  • schema 变 + 数据 backfill + 行为变更塞进一个迁移里。
  • 跳过”多少行”这个问题——所有安全判断都依赖它。
  • 只用 seed 数据测,看不出规模才暴露的 bug。

优化技巧

  • 在 PR 描述里写清表大小档位,让审查者(人或 AI)从事实出发。
  • expand → migrate → contract:永远别在一个 PR 里做完三步。
  • backfill 必带批次、sleep、replica 延迟节流和断点续跑。
  • Postgres:索引用 CONCURRENTLY、DDL 前 SET lock_timeout。MySQL:能用 ALGORITHM=INSTANT 就用,否则上 gh-ost 或 pt-online-schema-change。
  • 在生产形状的数据上测,别只用 seed。
  • 每个迁移 PR 都要回答:“周五下午 3 点上线,会出什么事?”
  • 回滚和迁移放同一个 PR。写不出回滚,就说明迁移不安全。

FAQ

  • 什么级别小到可以跳过审查?: 永远没有。老版本 MySQL 加默认值都可能重写或锁表,一条没加边界的 UPDATE 在 diff 里也只占一行。
  • 简单迁移能让 AI 自动通过吗?: 不行。让它提建议、给出 GREEN/YELLOW/RED 判定,由人签字。
  • 怎么准确估算迁移成本?: 把行数、平均行宽、并发 QPS 给审查者,再据此规划锁和 backfill。
  • 上班时间能跑迁移吗?: 小幅、仅改元数据的 additive 变更(且设了 lock_timeout)可以;重写型 schema 变更或大 backfill 走低峰。
  • 新 schema 需要 feature flag 吗?: 行为依赖新列被填充时需要。先把 schema 暗着上,backfill 完,再翻开关。
  • 写不出回滚怎么办?: 用 expand → migrate → contract 把迁移拆开。任何回滚不了的东西都是隐藏风险。

相关阅读

标签: #Prompt #编程 #数据库 #迁移 #Schema