实战:用 Agent 做数据库迁移与校验
系列入口:如何使用 Agent。M9 第 5 篇;前置连接数据库与内部 API。
一、迁移的特殊性:错误可能不可逆
代码写错了可以回滚重发,但数据库迁移一旦丢了列、覆盖了数据、或在大表上长时间锁表,后果可能无法挽回。这决定了迁移工作的第一原则:Agent 可以帮你写和分析,但对生产库的每一次执行都必须由人审批、在有备份和退路的情况下进行。
给 Agent 的数据库连接应遵循只读最小权限原则——它用来读结构、统计数据、生成脚本,而不是让它拿着写权限直接改库。迁移脚本生成后,真正的执行走受控流程。

二、第一步:备份并在副本上演练
任何正式迁移前,先确保有可用的备份,并确认备份真的能恢复——没验证过恢复的备份等于没有。
然后让 Agent 基于真实表结构和数据量级生成迁移脚本,先在副本或影子库(生产数据的快照)上完整跑一遍:能否成功、耗时多久、会不会锁表、占用多少资源。这个演练把"在生产上第一次发现脚本要跑三小时"的灾难提前暴露。让它同时统计相关表的行数、索引、外键和热点,作为后续校验基线。
三、第二步:可回滚与在线兼容设计
让 Agent 为每个迁移配回滚脚本(down),并诚实说明哪些操作其实难以回滚——比如删除的列在没备份时无法还原。对不可逆操作,应采用多步的兼容式迁移,而不是一步到位。
在线迁移的经典手法是"扩展—迁移—收缩":先新增结构(新列/新表)与旧结构并存,让代码双写或兼容读取;再分批把历史数据搬到新结构;最后等流量切换稳定后,才删除旧结构。这样每一步都可回退、且不需要长时间停机。让 Agent 帮你检查脚本的锁与长事务风险:大表更新要分批(小批量提交)、避开业务高峰、必要时用在线 DDL 工具,避免一条 ALTER 锁全库。
四、第三步:分批执行、灰度观察
正式执行时,小批量、分阶段推进,而不是一条命令全量跑完。
先在少量数据或低峰时段执行第一批,观察数据库负载、锁等待、应用报错和耗时是否符合演练预期;确认安全再逐步放量。执行窗口、进度和每批结果都留痕,出现异常立即暂停并按预案回退。整个过程人在现场把关,Agent 只负责生成脚本和解释现象。
五、第四步:多重校验,不能只看"命令成功"
迁移最忌"脚本跑完没报错"就当成功——结构对了不代表数据对。 用多层校验:
- 行数与总量对账:迁移前后记录数、关键汇总值是否一致、有无丢失或重复。
- 抽样核对:随机抽一批记录,逐字段比对新旧结构的值是否正确转换。
- 约束与完整性:外键、唯一约束、非空、索引是否就位,有无产生孤儿数据。
- 应用侧验证:通过真实功能读一遍新结构,确认业务行为正常。
让 Agent 生成这些校验查询和对账脚本,但结果由你核对。对大批量数据,全量逐行比对成本高,可"总量 + 分层抽样 + 关键字段哈希"组合,既高效又能抓住主要错误。
六、第五步:收尾与监控
切换稳定、观察期过后,再做收缩:删除临时结构/双写逻辑、回收冗余索引,并更新文档和数据字典。迁移后持续监控一段时间相关查询的性能——新结构可能改变执行计划,导致原本快的查询变慢。把本次迁移的脚本、校验结果和问题归档,沉淀为团队可复用的迁移模板与检查清单。
七、数据校验脚本的设计思路
迁移成败最终由校验回答,因此值得专门说说校验脚本怎么设计才靠得住,而不是临时凑几条查询。
核心思路是让校验独立于迁移脚本:迁移由 Agent 生成、校验也由它生成时,若两者共享同一个错误假设(比如对某字段转换规则理解错了),错误会同时出现在两边、还互相"验证通过"。所以校验的口径应回到需求独立确定,最好由另一个视角或人来定预期值。结构上分三层:第一层总量,迁移前后总行数、按关键维度分组的计数、重要汇总(金额总和等)是否一致,用来抓丢失、重复和整体错位,成本最低、应最先跑。
第二层抽样,随机且分层地抽一批记录(覆盖边界、特殊字符、空值、最大最小值),逐字段比对转换结果,用来抓"总量对但内容错"。第三层完整性,检查外键、唯一约束、孤儿数据、索引与新结构一致性。对超大表,可对关键字段计算分批哈希再汇总,既避免逐行拖垮库、又能敏锐察觉细微变化。校验脚本与迁移脚本一样要在影子库先验证——确认它在数据被故意改错时真的会报错,否则一个从不报警的校验和没有校验一样危险。
八、风险速查
| 风险 | 表现 | 对策 |
|---|---|---|
| 无法回滚 | 删列/改类型无备份 | 备份 + 扩展迁移收缩多步走 |
| 锁表/长事务 | 大表 ALTER、大批量 UPDATE | 分批、在线 DDL、低峰执行 |
| 数据丢失/错位 | 行数少、转换错误 | 对账 + 抽样 + 哈希校验 |
| 应用不兼容 | 发布后读不到字段 | 新旧并存、双写、灰度 |
| 性能退化 | 迁移后慢查询 | 索引核对、执行计划、监控 |
八、常见问题
Q:小改动(加个可空列)也要走这么重吗? 按风险伸缩。加可空列、无默认大值、不锁表的小变更可简化,但备份和回滚思路仍要保留;删列、改类型、动大表则必须走全套。
Q:Agent 说这条迁移"很安全",能信吗? 安全与否要靠副本演练、锁分析和真实数据量级说话,而不是它的判断;让它给出依据并亲自复核。
Q:迁移中途失败、执行了一半怎么办? 这正是分批 + 每步可回退的价值:暂停、按 down 脚本或备份恢复到一致状态,修好后重来;切勿在状态不明时继续硬跑。
Q:零停机迁移是不是必须的? 取决于业务是否允许维护窗口;允许停机可简单些,不允许就走扩展—迁移—收缩,成本更高但风险可控。
九、迁移完成后的数据字典与团队同步
技术上迁移成功只是一半,把变更清晰传达给使用该库的人,才能避免后续混乱和误用。
更新数据字典/ER 文档:新表、新列、字段含义、取值范围、索引和关系变化都要落到文档,最好能从库结构半自动生成、再补业务解释;废弃但暂时保留的旧结构应明确标注"待删除、勿用"。通知相关开发:说明新结构怎么用、查询是否需要改写、有无性能或语义差异,避免有人仍按旧模型写代码。归档迁移记录:脚本、校验结果、时间线和遇到的问题存档,作为下一次迁移的参考。
这一步看似文书工作,实则是迁移闭环的一部分——一个没人知道、文档缺失的"成功迁移",往往会在几周后以错误查询、重复建设的形式制造新成本。 让 Agent 帮忙生成初稿、核对结构,但业务含义和最终确认仍由人完成。
十、回滚预案要提前验证
迁移方案里最容易"写了等于没做"的就是回滚预案——人人都写了 down 脚本,却很少真的演练,真出事时才发现它不可用。
把回滚当作一等公民测试:在影子库不仅演练迁移、也要在迁移后真实执行一次回滚,确认数据能回到一致状态、应用能继续工作。诚实区分可逆与不可逆:删列、改类型这类操作光靠脚本往往无法完整回退,必须依赖备份,事先讲清楚、并验证备份恢复。设定明确的中止条件:出现哪些信号(锁等待超阈值、错误率上升、校验不符)就立即停止并回退,避免临场犹豫。
回退后再迁移的路径也要想清:修好问题后如何干净地重来。只有经过真实演练的回滚,才让"在线迁移、分批执行"真正有了底气,而不是把赌注押在"应该没问题"上。
十一、锁与长事务的具体判断
迁移对线上的最大冲击往往是锁,脚本动笔前就要让这类风险可见。
让 Agent 基于数据库类型和表量级分析:哪些 DDL 会锁全表、能否用在线 DDL 工具、大事务会持有锁多久、复制延迟会不会被拉大。大批量数据改写务必小批量提交、控制节奏,避免一个事务跑几小时。观察演练时的锁等待和耗时,作为正式执行的预期基线。在大表上,"能不能做"通常不是问题,"会不会拖垮在线服务"才是,这必须在低峰、分批、可中断的前提下处理。
十二、双写与切换期的一致性
走扩展—迁移—收缩路径时,中间的双写/切换期最容易产生数据不一致,需要专门设计校验。
明确以哪一侧为准、冲突如何解决、切换如何灰度;在切换期持续比对新旧两侧的计数与抽样,确认同步无误后才收缩旧结构。任何阶段都保留回退到旧结构的能力。这样虽然步骤更多,但把"一次性不可逆变更"拆成了一串每步都可验证、可撤销的小变更,这正是高风险迁移追求的确定性来源。
十三、迁移也要"可观测"
正式迁移期间,人无法靠肉眼盯着每一条数据,可观测性决定了异常能否在扩大前被察觉。
监控数据库的错误率、锁等待、负载和复制延迟,关注应用侧报错,并按批次核对进度与校验结果;设置明确阈值,一旦越线就自动告警、暂停执行。把每步结果留痕,事后可追溯。大迁移最怕"跑了一半才悄悄出错",而实时可见的指标和分批校验让问题在很小的批次就暴露,这比一条命令黑箱跑完再发现错位安全得多。让 Agent 帮忙生成监控查询和汇总,但暂停与回退的决定始终由人做出。
Q:业务要求一次性切换、无法双写怎么办? 那就更要靠备份、影子库全量演练和切换窗口内的快速校验兜底,并安排在低峰、准备好回退;允许停机的场景下,风险集中在切换那一刻,演练充分性比什么都关键。
十四、检查清单
- 已备份并验证可恢复,脚本已在副本/影子库演练。
- 有回滚脚本,采用在线兼容的多步迁移、分批提交。
- 已评估锁表与长事务,安排低峰执行。
- 已做行数对账、抽样/哈希、完整性与应用侧多重校验。
- 灰度放量、有监控与回退预案,收尾更新数据字典。
总结
用 Agent 做数据库迁移,安全来自"不信任、多验证":让它在只读权限下读结构、生成迁移与回滚和对账脚本,但执行必须人来审批;先备份并验证可恢复、在影子库完整演练,优先用"扩展—迁移—收缩"的在线兼容方式、小批量提交以避开锁表,再用行数对账、抽样哈希和应用验证多重确认数据无误,灰度执行、持续监控、最后才收缩;把"命令成功"和"数据正确、可回退"严格分开,才能在这种不可逆风险极高的操作里既用上 Agent 的效率、又守住数据安全。