From 86b9e696def0d683cbf1552d9f5727bed25365a8 Mon Sep 17 00:00:00 2001 From: chengma Date: Mon, 10 Aug 2026 02:22:44 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=BD=92=E6=A1=A3=E4=BB=BB=E5=8A=A1=20?= =?UTF-8?q?#79?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/task/79-mysql8-repository迁移.md | 58 +++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 docs/task/79-mysql8-repository迁移.md diff --git a/docs/task/79-mysql8-repository迁移.md b/docs/task/79-mysql8-repository迁移.md new file mode 100644 index 0000000..b87dd2c --- /dev/null +++ b/docs/task/79-mysql8-repository迁移.md @@ -0,0 +1,58 @@ +# 79 Admin:迁移 Repository SQL 与并发事务到 MySQL 8 + +- 类型:重构 +- 父级大工单:#76 +- 所属 MVP / 版本:#77 +- 状态:已完成 +- 日期:2026-08-10 +- Gitea 工单:http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/79 + +## 背景与目标 + +Admin Repository 原来依赖 SQLite 的 upsert、JSON、日期、分页和写事务语义,直接更换驱动会造成查询失败或并发行为变化。本任务把生产数据访问和启动入口迁移到 MySQL 8,并保持现有页面、Client 接口和业务契约不变。 + +## 最终方案 + +- 生产启动只读取 MySQL 环境变量,连接成功后执行追加式 MySQL schema 迁移。 +- 将 upsert、JSON 函数、LIKE 转义、保留字和不限条数查询改为 MySQL 8 语法。 +- 任务领取使用 `FOR UPDATE SKIP LOCKED`,状态更新和领取历史在同一事务提交。 +- 首位管理员初始化通过单行哨兵锁串行;客户端绑定通过锁定客户端行串行。 +- 并发同幂等键由唯一键决定赢家,失败事务回滚后读取并返回赢家响应。 +- 测试使用临时 MySQL 8.4 实例,每个测试创建随机独立数据库并在结束时删除。 + +与建单方案的差异:幂等提交没有只依赖缺失键的间隙锁,因为多个并发事务仍可能同时通过首次查询;最终采用唯一键冲突后回滚并复用赢家响应,结果更直接且不依赖隔离级别细节。 + +## 改了哪些 + +- `admin/main.go`:生产启动切换为 MySQL 配置、连接和迁移。 +- `admin/repository/*.go`:迁移生产 SQL,并补齐 InnoDB 并发事务语义。 +- `admin/repository/mysql_db.go`:追加 schema v2 管理员初始化哨兵表。 +- `admin/internal/testutil/mysql.go`:提供真实 MySQL 随机测试库和安全清理。 +- `admin/service/submit.go`:处理并发幂等唯一键竞争。 +- `admin/**/*_test.go`:业务与路由测试切换为隔离 MySQL,历史 SQLite 迁移测试继续保留。 +- `docs/admin/`:修正顺运宝缓存、JSON 函数和 SQLite 驱动用途说明。 + +## 验收结果 + +| 验收标准 | 结果 | +|---|---| +| Repository 生产 SQL 可在 MySQL 8.4 执行,不依赖 SQLite 方言 | 通过 | +| 并发领取同一任务只有一个客户端成功 | 通过 | +| 指定/无主领取、迟到/重派结果和幂等契约保持不变 | 通过 | +| 用户名和当前客户端归属唯一性、软删除规则保持一致 | 通过 | +| PDD JSON、筛选、分页和状态统计结果保持一致 | 通过 | +| Go 1.23 全量测试在隔离 MySQL 8.4 通过 | 通过 | + +## 测试 + +- 执行的命令:`GOTOOLCHAIN=local go test ./... -count=1 -timeout=20m`、`GOTOOLCHAIN=local go vet ./...`、`git diff --check` +- 结果:全部通过;真实 MySQL 8.4 全包测试中 `service` 用时 929.519 秒。 +- **没验证到的部分**:未连接、写入或切换线上生产 MySQL;生产数据迁移和部署由 #80、#81 验证。 + +## 遗留问题 + +- 真实 MySQL 跨公网测试每个用例独立建库,安全但耗时较长;不影响生产行为。 + +## 相关提交 + +- `13cfced` 迁移 Admin Repository 到 MySQL 8