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

58 lines
2.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 80 Admin:实现 SQLite 到 MySQL 8 单向迁移与核对
- 类型:需求
- 父级大工单:#76
- 所属 MVP / 版本:#77
- 状态:已完成,用户验收通过
- 日期:2026-08-10
- Gitea 工单:http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/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 单向迁移