Files
cmautobuy/docs/task/80-sqlite单向迁移.md

2.9 KiB
Raw Permalink Blame History

80 Admin:实现 SQLite 到 MySQL 8 单向迁移与核对

  • 类型:需求
  • 父级大工单:#76
  • 所属 MVP / 版本:#77
  • 状态:已完成,用户验收通过
  • 日期:2026-08-10
  • Gitea 工单:#80

背景与目标

历史业务数据保存在 SQLite admin.db,生产 Admin 改用 MySQL 8 前,必须完整迁移并证明人工关联、规格映射、账号、任务、客户端归属和同步游标没有遗漏。

最终方案

  • 命令必须显式选择 --dry-run、--execute 或 --verify-only,避免误执行。
  • SQLite 使用 mode=ro 和 query_only 双重只读,并检查 schema v8、quick_check 与外键。
  • MySQL 目标必须具有当前 schema 且 15 张业务表全空;非空目标直接拒绝。
  • 按外键依赖顺序在一个 MySQL 事务内复制全部业务列,保留主键、时间、JSON 和哈希原文。
  • 导入后比较每张表的数量与全部迁移列的确定性 SHA-256 摘要,并检查关键孤儿关系和当前归属唯一性。
  • 对外错误只包含阶段和表名,不透出可能含业务主键的数据库原始错误。

与建单方案一致。额外增加全列摘要核对,比仅比较行数更能发现字段漏迁或内容变化。

改了哪些

  • admin/cmd/migrate-sqlite-to-mysql/main.go:一次性迁移命令和三种显式模式。
  • admin/repository/sqlite_to_mysql.go:只读检查、空库门禁、事务复制和核对。
  • admin/repository/sqlite_to_mysql_test.go:真实 MySQL fixture、失败回滚和重复保护测试。
  • docs/admin/09-sqlite迁移到mysql.md:演练、执行、核对、失败处理和切换门禁。
  • docs/README.md、docs/admin/00-getting-started.md:补充迁移文档入口。

验收结果

验收标准 结果
只读打开 SQLite,失败不修改源文件 通过
非空 MySQL 目标默认拒绝 通过
v8 全表迁移后数量与全列摘要一致 通过
关键业务关系、归属、任务、幂等与游标一致 通过
重复执行不会重复导入 通过
输出不包含凭据、Cookie、Session 或业务明细 通过
提供可复制的演练、核对和失败处理命令 通过

测试

  • 执行的命令:真实 MySQL fixture 定向测试;对当前 admin/data/admin.db 依次执行 --dry-run、--execute 和 --verify-only;GOTOOLCHAIN=local go build ./...、go test ./...、go vet ./...、git diff --check。
  • 结果:Go 1.23.0 全部通过;真实 25 MB SQLite 的 15 张表约 1.67 万行完成迁移并两次核对通过;源文件 SHA-256 前后相同。
  • 没验证到的部分:未连接或修改线上生产 MySQL;线上备份、停写、正式迁移与 Admin 切换由 #81 验证。

遗留问题

  • 跨公网逐行迁移约 1.67 万行用时约 9 分钟;线上同机迁移预计更快,但仍应安排停写窗口。

相关提交

  • c296fea 实现 SQLite 到 MySQL 单向迁移