--- 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` 一致。