mysql乐观锁和悲欢锁
MySQL中的乐观锁和悲观锁是解决数据库并发访问冲突的两种核心策略,它们在设计理念和实现方式上有显著区别:
一、悲观锁(Pessimistic Locking)
核心理念:假设冲突必然发生,操作数据前先加锁独占资源。
实现方式:通过MySQL的锁机制(如SELECT ... FOR UPDATE或SELECT ... LOCK IN SHARE MODE)实现。
适用场景:写操作频繁、冲突概率高的场景(如账户扣款、库存争抢)。
START TRANSACTION;
-- 锁定查询到的行(其他事务无法修改)
SELECT * FROM products WHERE id = 1 FOR UPDATE;
-- 执行业务逻辑(如扣减库存)
UPDATE products SET stock = stock - 1 WHERE id = 1;
COMMIT;
特点:
-
优点:保证强一致性,避免并发冲突。
-
缺点:
-
加锁增加系统开销,降低并发性能。
-
可能引发死锁(需事务及时提交/回滚)。
-
锁粒度控制不当易导致性能问题(如行锁升级为表锁)。
二、乐观锁(Optimistic Locking)
核心理念:假设冲突很少发生,提交操作时再检测冲突。
实现方式:通过版本号(version)或时间戳字段实现无锁并发控制。
适用场景:读多写少、冲突概率低的场景(如评论更新、配置修改)。
-- 先查询当前版本号
SELECT stock, version FROM products WHERE id = 1;
-- 执行业务逻辑(内存中计算新值)
-- 更新时校验版本号
UPDATE products
SET stock = stock - 1, version = version + 1 WHERE id = 1 AND version = 旧版本号;
-- 检查是否更新成功(影响行数 > 0)
特点:
-
优点:
-
无锁设计,并发性能高。
-
避免死锁风险。
-
缺点:
-
冲突时需重试或回滚,增加业务逻辑复杂度。
-
不适用高冲突场景(频繁重试可能降低性能)。
-
存在ABA问题(可通过递增版本号解决)。
三、关键对比
特性
悲观锁
乐观锁
冲突假设
必然发生
很少发生
实现方式
内置锁机制(FOR UPDATE)
版本号/时间戳字段
加锁时机
操作前加锁
提交时检查
性能影响
高开销(锁竞争)
低开销(无锁)
适用场景
高并发写、强一致性要求
低冲突、高并发读
复杂度
数据库层控制,业务逻辑简单
需业务层处理重试
典型用例
库存扣减、金融交易
更新用户信息、统计计数
四、如何选择?
- 悲观锁适用:
-
事务涉及多表复杂更新。
-
业务逻辑无法容忍重试(如支付交易)。
-
冲突频率高(如秒杀场景)。
- 乐观锁适用:
-
读操作远多于写操作。
-
冲突概率低(如CMS内容编辑)。
-
系统要求高吞吐量(如日志记录)。
乐观锁以版本检测换性能,悲观锁以提前加锁保安全。根据业务场景的冲突概率、一致性要求及性能需求权衡选择,必要时可组合使用(如读用MVCC、写用悲观锁)。

发表评论
所有评论