Files
cmautobuy/docs/task/79-mysql8-repository迁移.md

3.0 KiB

79 Admin:迁移 Repository SQL 与并发事务到 MySQL 8

  • 类型:重构
  • 父级大工单:#76
  • 所属 MVP / 版本:#77
  • 状态:已完成,用户验收通过
  • 日期:2026-08-10
  • Gitea 工单:#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