312 字
2 分钟
MySQL 乐观锁与悲观锁:冲突少时重试,冲突多时排队
乐观锁假设冲突较少,更新时再检查版本;悲观锁假设冲突会发生,操作前先取得锁。
两种实现
悲观锁常用 SELECT ... FOR UPDATE 获取排他锁,或使用共享锁;其他事务需要等待当前事务提交或回滚。乐观锁通常增加 version 字段:读取版本,更新时在 WHERE 中带上旧版本,影响行数为 0 时说明发生冲突,由业务决定重试或报错。
如何选择
读多写少、同一行冲突概率低时适合乐观锁;秒杀等写冲突密集场景,持续重试的乐观锁可能更慢,悲观锁排队反而更稳定。也可以平时使用乐观策略,冲突率升高时切换处理方案。
更新失败率过高怎么办
可以把库存拆成多个桶降低热点,使用消息队列合并请求,或直接改用悲观锁排队。
FOR UPDATE 锁行还是锁表
取决于是否走索引。命中索引时锁满足条件的记录;没有合适索引时可能扫描并锁住大量记录。可重复读下还可能加间隙锁,锁的范围会大于单行。
MySQL 乐观锁与悲观锁:冲突少时重试,冲突多时排队
https://blog.xqcherry.top/posts/interview/mysql/optimistic-vs-pessimistic-lock/ 目录