Files
zt-closet-backend/.codebuddy/plans/数据库唯一索引全面补齐_0a7c6d59.md
2026-09-11 01:41:52 +08:00

82 lines
5.8 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.
---
name: 数据库唯一索引全面补齐
overview: 全面盘点代码中依赖数据库唯一索引做幂等/防重、但模型未声明 tag 的表,补全 GORM 模型 tag,并生成一份幂等的建索引 SQL 脚本供用户自行在开发库执行。
todos:
- id: add-model-unique-index-tags
content: 为 vipflowlog、benefit_grant_task、refundflowlog、collect、like、order、quota(UserDailyUsage)、horoscope 八个模型补 uniqueIndex tag
status: completed
- id: create-sql-script
content: 新建 sql/unique_indexes.sql:9 条唯一索引 DDL、幂等检查语句、执行说明与重复数据清理提示
status: completed
dependencies:
- add-model-unique-index-tags
- id: build-verify
content: 执行 go build、go vet 与 lint 检查,核对脚本索引与模型 tag 一一对应
status: completed
dependencies:
- create-sql-script
---
## 产品概述
针对上一轮「配额流水事务一致性修复」遗留的数据库唯一索引落地问题,为开发环境提供一套完整的数据库唯一索引补齐方案。用户处于开发阶段、无历史业务数据,选择由本人后续自行在开发库执行 SQL,本次交付:补全所有依赖唯一索引做幂等/防重的模型声明,并生成可直接执行的幂等 SQL 脚本。
## 核心功能
- **补全模型唯一索引声明**:为 8 个依赖唯一索引但未声明 gorm tag 的模型补充 `uniqueIndex` 声明(自文档化,不影响当前运行)。
- **生成唯一索引 SQL 脚本**:新建 `sql/unique_indexes.sql`,覆盖 9 个表的唯一索引 DDL,每条附用途说明与依赖代码位置。
- **提供幂等执行与清理指引**:脚本头部提供索引存在性检查语句与重复执行说明,尾部提供开发环境重复测试数据的清理提示。
- **构建验证**:确保 tag 改动无编译、静态检查错误。
## 索引清单
| 表 | 唯一索引(建议名) | 依赖场景 |
| --- | --- | --- |
| quota_flow_logs | uk_quota_flow_idem (order_no, quota_type, change_type) | 配额发放/回收幂等(tag 已补,仅需 SQL) |
| vip_flow_logs | uk_vip_flow_idem (order_no, change_type) | VIP 发放/回收幂等 |
| benefit_grant_tasks | uk_benefit_task_idem (order_no, benefit_type) | 权益发放补偿任务幂等凭证 |
| refund_flow_logs | uk_refund_flow_no (refund_no) | 退款申请防重 |
| collects | uk_collect_user_target (collect_type, target_id, user_id) | 收藏/取消收藏 upsert |
| likes | uk_like_user_target (like_type, target_id, user_id) | 点赞/取消点赞 upsert |
| orders | uk_order_no (order_no) | 商户订单号唯一 |
| user_daily_usages | uk_daily_usage_user_date (user_id, stat_date) | 每日计数行唯一,防并发重复行 |
| horoscopes | uk_horoscope_date_zodiac (stat_date, zodiac) | 每日星座运势防重复生成 |
## 技术栈
- 语言:Go
- ORM:GORM(`uniqueIndex` tag 声明,`priority` 控制联合索引列顺序)
- 数据库:MySQL 8.0(`ALTER TABLE ... ADD UNIQUE INDEX`)
- 脚本形式:纯 SQL 文件,人工执行
## 实现方案
### 总体策略
项目无迁移机制(无 AutoMigrate、无 .sql 文件、表结构外部管理),用户已明确选择「自己执行 SQL」,因此本次改动仅两处:模型 tag 补全 + 新增 SQL 脚本。不引入 AutoMigrate、不改服务启动行为。tag 声明仅作代码自文档化,为未来可能启用的自动迁移预留基础。
### 模型 tag 补全(8 个文件)
1. `internal/mysqlmodel/vipflowlog.go`:`OrderNo` + `ChangeType` 联合索引 `uk_vip_flow_idem`(priority 1/2)。
2. `internal/mysqlmodel/benefit_grant_task.go`:`OrderNo` + `BenefitType` 联合索引 `uk_benefit_task_idem`(priority 1/2)。
3. `internal/mysqlmodel/refundflowlog.go`:`RefundNo` 单列唯一索引 `uk_refund_flow_no`。
4. `internal/mysqlmodel/collect.go`:`CollectType` + `TargetID` + `UserID` 联合索引 `uk_collect_user_target`(priority 1/2/3)。
5. `internal/mysqlmodel/like.go`:`LikeType` + `TargetID` + `UserID` 联合索引 `uk_like_user_target`(priority 1/2/3)。
6. `internal/mysqlmodel/order.go`:`OrderNo` 单列唯一索引 `uk_order_no`。
7. `internal/mysqlmodel/quota.go`(`UserDailyUsage`):`UserID` + `StatDate` 联合索引 `uk_daily_usage_user_date`(priority 1/2)。
8. `internal/mysqlmodel/horoscope.go`:`StatDate` + `Zodiac` 联合索引 `uk_horoscope_date_zodiac`(priority 1/2)。
tag 格式遵循现有项目约定(如 `quotaflowlog.go`、`quota.go` 已声明的 `uniqueIndex:名称,priority:N` 风格),保持注释说明索引用途。
### SQL 脚本设计(新建 sql/unique_indexes.sql)
- **头部**:执行说明(目标库、开发环境定位、执行方式 `mysql -u... -p... < sql/unique_indexes.sql`);MySQL 8.0 不支持 `CREATE INDEX IF NOT EXISTS`,提供基于 `information_schema.statistics` 的索引存在性检查模板查询。
- **主体**:9 条 `ALTER TABLE xxx ADD UNIQUE INDEX xxx (...)`,按上表顺序排列,每条以注释块说明用途、依赖代码位置、重复执行时预期行为(已存在会报 Duplicate key name,可忽略或先删后建)。
- **尾部**:开发阶段如有重复测试数据需先清理的提示,并给出关键表的查重 SQL 示例(如 `SELECT order_no, COUNT(*) FROM quota_flow_logs GROUP BY order_no, quota_type, change_type HAVING COUNT(*) > 1;` 模板)。
- **不包含**:任何 `DROP TABLE`、`TRUNCATE`、删除数据的自动执行语句;清理数据仅以注释形式提示,由用户手动确认执行。
### 验证
- `go build ./...`、`go vet ./...`、`read_lints` 检查 tag 改动相关文件,确保无新增错误(tag 为纯字符串注释性元数据,预期零编译影响)。
- 人工核对脚本中 9 个索引与模型中 tag 声明一一对应,列顺序与 `priority` 一致。