批量数据库操作防重复需分层防御:前端用batchtoken前置幂等,中间按主键哈希分片加分布式锁,数据库建唯一索引兜底并用insert ignore等语法处理冲突,异常需友好提示、日志可追溯。

批量数据库操作遇到重复主键冲突,不能靠“试了再说”硬扛,得有分层防御策略:前端防重、中间加锁、数据库兜底、异常善后。核心是让重复请求在穿透到数据库前就被识别或拦截,而不是等报错再补救。
前置幂等标识:用 batchToken 控制整批唯一性
用户手动触发的批量导入(如 Excel 上传),必须由前端生成唯一 batchToken(如 UUID),随请求一起传给后端。后端收到后立即执行:
- 用 Redis SETNX 命令写入 batchToken:xxx,并设置合理过期时间(如 5 分钟)
- 写入成功才继续处理;失败则直接返回“该批次已在处理中,请勿重复提交”
- 整个批次处理完成后再主动删除 token,或依赖自动过期兜底
分片加锁:按主键特征隔离并发线程
单体应用可用本地锁,多节点部署必须用 Redis 分布式锁,关键在于锁粒度要和主键重复风险对齐:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 按主键哈希或取模分片(如 order_no.hashCode() % 16),确保相同主键总落在同一分片
- 每个分片对应一把独立锁(ConcurrentHashMap
或 Redis key 如 import:shard:7) - 线程只在自己分片锁内做「查存在 → 插入」或直接用 INSERT IGNORE / ON DUPLICATE KEY UPDATE
数据库强制约束:唯一索引是最后一道铁闸
无论加多少层锁,都必须在数据库主键字段及业务唯一字段(如 order_no、user_id + biz_type)上建 UNIQUE 索引:
- 这是最可靠、不可绕过的防线,能真正阻止非法数据落库
- 批量插入时优先选用支持跳过冲突的语法(MySQL 用 INSERT IGNORE,PostgreSQL 用 ON CONFLICT DO NOTHING)
- 捕获 SQLIntegrityConstraintViolationException,检查异常信息是否含 Duplicate entry 或 PRIMARY 关键字,再统一转为友好提示(如“第3条数据已存在,已跳过”)
异常降级与结果反馈:不掩盖问题,也不暴露细节
主键冲突异常不是 bug,而是可预期的业务分支,处理逻辑要清晰透明:
- 绝不吞掉异常后静默失败;也不把原始数据库报错堆栈返回给前端
- 区分场景响应:用户提交类操作提示“该单号已存在”,后台任务可转为更新逻辑
- 记录日志时带上 batchToken、冲突主键值、分片编号,便于问题定位和数据核对
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










