高并发下数据库锁竞争需通过缩小事务粒度、减少锁范围和时长来解决,而非增加锁;应避免长事务、确保索引优化、合理使用隔离级别与锁类型、区分读写场景,并在低冲突场景采用乐观锁。

高并发下数据库锁竞争不是靠“加更多锁”解决的,而是要让锁更准、更短、更少——核心是把事务粒度和锁范围压到最小,同时避开数据库层的隐式锁升级和长事务陷阱。
事务边界必须紧贴业务原子性
一个事务不该包含日志记录、远程调用、复杂计算或非必要查询。这些操作一旦失败或超时,会拖长事务持有时间,导致行锁/间隙锁长期占用。
- 把数据库操作单独抽成最小闭环:比如“扣库存 + 更新订单状态”是一组,但“发短信通知”必须异步化
- 避免在事务中调用其他服务接口——网络延迟不可控,极易引发锁等待雪崩
- 用 Spring 的 @Transactional 时,明确指定 propagation = Propagation.REQUIRED 和 isolation = Isolation.READ_COMMITTED,不盲目用默认或 SERIALIZABLE
写操作优先用行级锁 + 明确条件
MySQL InnoDB 默认对 WHERE 条件命中索引 的 UPDATE/DELETE 加行锁;若条件没走索引,会退化为表锁或全表扫描锁,高并发下直接卡死。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 确保 where 字段有唯一索引或联合索引覆盖,例如 UPDATE order SET status=2 WHERE order_no='xxx'(order_no 建唯一索引)
- 禁用无条件更新:UPDATE products SET stock = stock - 1 是灾难——它会锁全表或所有聚簇索引项
- 读已提交(READ COMMITTED)下,间隙锁仅在唯一索引等值查询时抑制,非唯一索引或范围查询仍会加间隙锁,需结合业务评估是否可接受幻读
读多写少场景主动降级读锁强度
不是所有读都需要加锁。高并发查配置、查商品详情、查用户信息等,应区分“一致性读”和“当前读”。
立即学习“Java免费学习笔记(深入)”;
- 普通查询一律用快照读(普通 SELECT),不加锁,依赖 MVCC 保证 RC 隔离级别下的可见性
- 仅在真正需要“防止覆盖写”的场景才用 SELECT ... FOR UPDATE 或 SELECT ... LOCK IN SHARE MODE
- 对缓存穿透敏感的数据(如热点商品),可搭配本地缓存(Caffeine)+ 短 TTL(如 10s)+ 分布式锁预热,避免大量请求同时击穿到 DB 触发行锁争抢
乐观锁替代悲观锁处理低冲突更新
适合状态流转类操作(如订单从“待支付”→“已支付”)、计数器类(如点赞数、浏览量),冲突概率低但并发量大。
- 在表中增加 version 字段,UPDATE 时校验:UPDATE order SET status=2, version=version+1 WHERE id=123 AND version=5
- 执行后检查影响行数,为 0 则说明被其他线程抢先更新,业务侧重试或返回失败
- 比悲观锁减少锁等待、避免死锁,且不依赖数据库锁机制,更适合分布式伸缩

















