生产备份本地恢复修复
背景
本地 idc 在直接导入生产备份 idc_2026-07-26_22-06-47_mysql_data_JWLTb.sql 时于第 715 行失败。该行是 integration_plugin_runtime_logs 的大批量日志 INSERT,包含上游响应中的 JSON/JavaScript 文本。失败后本地仅保留 17 张表,migrations 表不存在,不能作为可运行开发库。
生产备份的共同表结构与当前基线大体一致,但备份保留旧的自引用 product_groups,未包含当前代码所需的 first_product_groups、second_product_groups 和 third_product_groups。恢复必须在隔离库中完成数据导入与商品分组转换,不能将旧 DDL 直接覆盖本地当前结构。
范围与验收
- [x] 保全当前部分恢复的
idc,不覆盖、不删除其数据。 - [x] 在唯一命名的临时库中复现并定位第 715 行导入失败,不向生产或当前
idc写入。 - [x] 用当前
mysql-schema.sql建立候选库,并以受控映射恢复生产数据。 - [x] 将旧
product_groups三层树转换为当前三张分组表;所有无法确定的父级或商品归属必须阻断并产出异常清单。 - [x] 验证候选库 62 张表、迁移元数据、关键财务行数、外键、商品分组层级和 Laravel 数据库连通性。
实施步骤
- 记录备份 SHA-256 与本地
idc结构快照,并生成可恢复的本地部分库备份。 - 使用原生
mysql客户端向独立探测库导入备份;若第 715 行复现,重新从生产以--skip-extended-insert导出日志表,保留全部记录并定位异常行。 - 基于当前 schema baseline 新建候选库;禁止使用会重置并播种默认数据的总控安装脚本作为恢复入口。
- 复用并校正现有
migrate_legacy_dump.py的流式数据映射能力:共同表仅导入数据,旧product_groups按层级转换,不恢复旧表结构。 - 在候选库执行逐表行数、关键关系、商品分组和应用连接验证;通过后再由用户确认是否向候选库授予既有本地应用账号权限并切换
DB_DATABASE。
风险与回滚
- 当前
idc是不完整库,禁止DROP DATABASE、install_db.py --reset或对其直接执行迁移脚本。 - 商品分组二级、三级记录的父级映射不可猜测;缺失或越级记录必须停止转换,不能静默挂到默认分组。
integration_plugin_runtime_logs为审计数据。可在候选库首轮恢复时延后导入以恢复应用,但不能通过永久丢弃该表数据解决导入错误。- 所有 DDL 和 DML 限定在新建候选/临时库;只有验证通过并获得用户确认后才向候选库授予既有本地应用账号权限、变更本地连接目标或清理临时库。
进度
- [x] 已完成源备份、当前本地库和代码 schema 的只读差异审计。
- [x] 已创建并完成隔离导入探测库。
- [x] 已生成并验证候选库数据映射。
- [x] 已完成候选库验收;未变更应用配置。
- [x] 已将候选库完整恢复至本地
idc,并恢复本地后端常驻进程。
本轮证据(2026-07-26)
- 已将部分恢复的
idc完整备份到系统临时目录,恢复用的无 GTID 版本 SHA-256 为C64EA3A59DA0FCB63E7FABB7333FDEE279C09418A4DF9F398BF668696017DD34;现有idc未被写入或清空。 - 原始生产备份 SHA-256 为
703418D549366BB8733A787109E7C311895502696322692456BE78AE20434AEF。原生mysql.exe已在idc_temp_restore_probe_20260726_2240完整导入成功,故截图中的 1064 属于原先导入路径,而非该 dump 的 SQL 或本地表结构。 - 候选库
idc_temp_restore_candidate_20260726_2246由当前 schema baseline 初始化后完成数据映射:57 张映射表、381,232 条数据,包含全部 14,889 条integration_plugin_runtime_logs审计记录。 - 验收通过:62 张基础表、174 条迁移元数据、57 张映射表行数零差异、92 个外键约束零孤儿、运行态表为空;Laravel 商品分类巡检零阻断/零警告。
- 2026-07-27 已按用户确认将候选库完整恢复至
idc:替换前idc有 16 张基础表,替换后为 62 张;候选库与idc的 62 张表逐表行数、视图/例程/触发器/事件数量均一致,92 个外键约束零孤儿。 - 恢复后 Laravel 实际连接为
idc(62 张基础表);商品分类巡检零阻断/零警告,migrate:status通过,http://127.0.0.1:8000/api/health返回 200。原有 app server、schedule worker 与 VNC relay 已按原命令恢复。
决策日志
| 日期 | 决策 | 原因 |
|---|---|---|
| 2026-07-26 | 不复用直接恢复旧 DDL 的方式。 | 生产备份与当前分组物理结构不一致,直接恢复会留下缺失的三层分组表。 |
| 2026-07-26 | 先在隔离候选库验证,再考虑替换本地 idc。 | 当前库已部分导入,任何重置都会丢失排障证据和可回滚状态。 |
| 2026-07-26 | 使用宝塔自带原生 mysql.exe 完成探测导入。 | 同一原始字节流导入成功,排除第 715 行日志 JSON、字符集和本机包大小作为根因。 |
| 2026-07-26 | 保留候选库,不自动授予应用账号权限或变更 backend/.env。 | 既有应用账号仅拥有 idc.* 权限;切换候选库会影响正在运行的本地服务,必须由用户明确决定。 |
| 2026-07-27 | 按用户明确要求将候选库完整恢复至 idc,不修改 .env。 | 用户要求的是本地 idc 的全量替换,而非将应用改指向候选库;候选库和回滚备份保留。 |
