站内精选

一句话结论

数据库迁移可以交给 AI 写,但顺序得反过来:先让它出回滚脚本和验证 SQL,再补正向脚本,一步对一步编号。

这篇解决什么问题

上周给订单表加一个渠道字段,需求单只有三行,写脚本加上想清楚怎么撤,占了大半天。适用:MySQL 或 PostgreSQL 的表结构变更,尤其是加列、改字段类型、加索引这类要上线又不能出事的改动。不适用:跨库数据迁移、分库分表重分布这种要停机窗口、要专门工具的大工程。

开始前要准备什么

  • DeepSeek 网页版,免费额度够跑完这篇的对话量
  • Cursor 用来改脚本和跑终端,免费额度可覆盖,重度用需付费
  • 本地 Docker 起一个 MySQL 8.0 实例,专门用来演练
  • 一份变更需求原文,写清表名、字段、行数量级
  • 相关表的建表语句,也就是 SHOW CREATE TABLE 的结果
  • 预计耗时:单表变更通常 30 到 60 分钟,含本地演练

具体怎么做

第 1 步 · 把需求整理成结构化输入

别急着要 SQL。先让它把需求翻译成变更项清单,这一步决定了后面脚本的完整度。我在实操中发现,跳过这步直接要代码,十有八九会漏掉回填和锁表风险。

你是资深 MySQL DBA。下面是一次表结构变更的需求原文,请先别写 SQL,只做三件事:1) 把需求拆成按依赖排序的变更项清单,每项写清表名、列名、类型、是否可空、默认值;2) 标出每项对现有数据的影响,包括是否需要回填、是否需要重建索引、是否会锁表;3) 列出这次变更可能波及的上游查询和定时任务。
需求原文:在 shop_demo 库做两处调整。t_order 增加 channel_code varchar(16) 非空默认 ‘web’,并对 channel_code 和 created_at 建联合索引;t_user_profile 的 phone 从 varchar(32) 改为 varchar(64),允许为空。t_order 约 800 万行,t_user_profile 约 120 万行,MySQL 8.0.32,InnoDB。
输出用表格,这一轮不要给 SQL。

预期产出:一张按依赖排序的变更项表,每行标出锁表风险和回填范围。

第 2 步 · 先要一份回滚脚本

顺序很关键。回滚是”从目标态退回原态”,先把退路定死,正向脚本才有明确的对照物。反过来做的话,回滚基本是倒着编的,编号对不上还容易漏项。

基于上一步的变更清单,现在只写回滚脚本,不要写正向脚本。约束:1) MySQL 8.0 语法,每条语句能单独执行,不要用一个大事务把整体包住;2) 每条 SQL 上方加一行注释,写明它撤销的是哪一项变更、什么情况下必须执行;3) 不可逆操作单独列出来,比如把字段从 varchar(64) 收回 varchar(32) 或者删列,先给一条执行前的检查 SQL;4) 回滚顺序就是正向顺序的逆序,编号用 R1、R2、R3 对应变更项。
输出三段。第一段三行内说明回滚顺序与适用场景。第二段是完整 SQL。第三段是回滚后的自检 SQL,用来确认表结构确实回到了变更前的状态。

预期产出:一份逆序排列的回滚 SQL,外加一段回滚后的结构自检语句。

第 3 步 · 再补正向脚本,编号对齐

这一步要把算法选项钉死。加列走 INSTANT 还是 COPY,差别可能是秒级和分钟级。AI 默认不会主动说,你得点名要它给判断。

现在写正向迁移脚本。要求:1) 每条和上一步的回滚脚本一一对应,编号用 P1、P2、P3 对应 R1、R2、R3;2) t_order 加列用 ALGORITHM=INSTANT,如果你判断我的版本不支持,直接说明并给降级写法;3) 联合索引用 CREATE INDEX,带上 ALGORITHM=INPLACE, LOCK=NONE;4) phone 扩长用 MODIFY COLUMN,明确告诉我这次会不会走 COPY 算法、大致影响多久;5) 脚本要能重复执行,加列加索引之前先查 information_schema 判断是否已存在,把判断 SQL 也写出来;6) 不要出现 DROP TABLE 和 TRUNCATE。
输出带编号的 SQL 代码块,每个编号后面跟一行中文说明。

预期产出:编号与回滚一一对应的正向脚本,每个编号带一行执行说明。

第 4 步 · 让它写验证 SQL

脚本能跑不等于迁移成功。真正要确认的是:默认值有没有覆盖到历史行。下面这段我特意要求分三段,就是为了把”迁移前、迁移后、回滚后”三个状态都留证据。

为这套迁移写一份验证清单,分三段。第一段迁移前:确认表结构基线、行数、索引现状的 SQL。第二段迁移后:确认字段类型、默认值、索引真的生效的 SQL,再加数据抽样,核对默认值是否覆盖了全部历史行。第三段回滚演练后:确认结构复原的 SQL。每条都要给可直接执行的 SQL,并注明期望结果是什么、不符合期望说明什么。
最后单独回答一个问题:这套迁移里你认为最可能在线上失败的一个点是什么,为什么。

预期产出:三段式验证 SQL 清单,每条附期望结果和异常解释。

第 5 步 · 在本地容器里演练两轮

正向跑一遍、回滚再跑一遍,两轮都过才算这套脚本可用。造数据的时候要盯着它别偷懒,channel_code 全是同一个值,验证就等于没做。

我要在本地 Docker 起的 MySQL 8.0 里把这次迁移演练一遍。给我一份演练顺序:1) 造测试数据的最小 SQL,t_order 和 t_user_profile 各一段,10 万行级别,channel_code 要有空值和至少三种取值,不要全是同一个默认值;2) 正向执行、验证、回滚、再验证这四步的终端命令顺序,一条一行;3) 每一步执行完我该看什么输出,看到什么才算这一步通过。
命令按 Linux 终端写,我用 Cursor 的终端直接跑。

预期产出:一套能在本地跑完的两轮演练命令,附每步通过标准。

实测记录

两个工具都在各自的免费额度内跑完,没有额外支出。下面是我这单的真实节奏,行数级别和上面需求原文一致。

环节 实际情况
整理需求到第一版方案 约 15 分钟,追问两次才把行数量级说清
生成正向与回滚脚本 约 10 分钟,两轮对话
本地演练正向加回滚各一遍 约 40 分钟,第二轮才全过
手工写同样两份脚本做对照 半天左右,还得找人帮忙看一眼
返工的地方 第一版漏了历史空值的回填顺序

最容易错的 3 个地方

  1. 先写正向再让 AI 补回滚,编号对不上还漏项。改:回滚先行。
  2. 加非空默认值列直接 ALTER,历史行被填了默认值。改:先可空后回填。
  3. 只演练正向不演练回滚,出事那天撤不回来。改:两轮都要跑。

第二条是我踩得最实的一次:业务上那批老订单根本没有渠道概念,填上 ‘web’ 之后报表口径直接错了,最后是补了一次数据订正才拉回来。

可复用的东西

这五段提示词其实是一套固定套路:结构化需求、回滚先行、正向对齐、三态验证、本地演练。换下一个变更,只需要改中间那段需求原文和行数量级。

我把它存成了一个模板,其它约束基本不用动。库名表名一律用化名,别把真实表结构直接贴进对话。这套流程跑顺之后,迁移脚本这件事就不再是上线前夜最慌的那一环了。

你手上最近一次表结构变更,回滚脚本是提前写好的,还是出问题那天现补的?

常见问题解答

AI 生成的迁移脚本能直接跑生产吗?

不能。它默认不知道你的真实行数、版本细节和索引现状。先在本地容器把正向和回滚各跑一遍,再按变更窗口分批执行。

为什么一定要先写回滚再写正向?

回滚是从目标态退回原态,先定好退路,正向脚本才有明确对照物。反过来写,回滚往往是倒着编的,容易漏项、编号也对不上。

表行数很大,AI 给的 ALTER 还能用吗?

要看它有没有显式给算法选项。MySQL 8.0 加列可走 INSTANT,改字段类型多为 COPY,几百万行以上建议错峰或用在线工具做,别只信默认脚本。

小程序阅读免费
微信扫码进入小程序,按岗位找 AI 实操步骤
微信扫码进小程序
按岗位找 AI 实操步骤 · 提示词可收藏

发表回复

后才能评论