防重核心是写入前拦截,首选唯一约束保底线,辅以ON DUPLICATE KEY UPDATE或INSERT ON CONFLICT等原子语句,配合幂等键校验,避免先查后插引发的竞态问题。

防止重复写入,核心不是只靠SQL去重语句(如 DISTINCT 或 GROUP BY),而是要在数据写入前就拦住重复——靠约束保底线,靠逻辑控流程。
用唯一约束(UNIQUE)锁死重复入口
这是最直接、最可靠的防重手段。在业务上天然不能重复的字段组合(如手机号、订单号、用户+日期组合)上建唯一索引或唯一约束,数据库会在 INSERT/UPDATE 时自动拒绝违反约束的操作。
- 建表时加:`CREATE TABLE user_log (user_id INT, log_date DATE, UNIQUE(user_id, log_date));`
- 已有表加:`ALTER TABLE user_log ADD CONSTRAINT uk_user_date UNIQUE (user_id, log_date);`
- 插入时捕获异常(如 MySQL 的 1062 错误码),程序中友好提示“该记录已存在”,而不是让报错穿透到前端
INSERT ... ON DUPLICATE KEY UPDATE(MySQL)或 MERGE(SQL Server/PostgreSQL)
当需要“有则更新、无则插入”时,用这类原子语句替代先查后插的逻辑,避免竞态条件(两个请求同时查不到、同时插入成功)。
- MySQL 示例:`INSERT INTO user_points (uid, points) VALUES (123, 10) ON DUPLICATE KEY UPDATE points = points + 10;`(前提是 uid 或组合有唯一约束)
- PostgreSQL 推荐用 `INSERT ... ON CONFLICT DO UPDATE`,语义更清晰,支持 WHERE 条件过滤更新范围
- 注意:这类语句依赖唯一约束触发冲突判断,没约束就退化为普通插入,起不到防重作用
应用层加幂等标识 + 数据库校验
对无法强约束的场景(如异步消息、第三方回调),由调用方提供幂等键(如 request_id、trace_id),写入前先查该 ID 是否已处理。
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。
还木有评论哦,快来抢沙发吧~