59 lines
3.0 KiB
Markdown
59 lines
3.0 KiB
Markdown
# 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
|