
乐观锁和悲观锁不是数据库自带的“开关”,而是通过不同设计思路实现的并发控制策略。选哪种,取决于业务场景对数据冲突频率、响应速度、系统复杂度的权衡。
乐观锁:适合读多写少、冲突概率低的场景
核心是“先查后验”,不加锁,靠版本号或时间戳判断数据是否被修改过。执行更新时,SQL 中必须包含校验条件。
- 典型写法:UPDATE order SET status = 'shipped', version = version + 1 WHERE id = 123 AND version = 5 —— 若影响行数为 0,说明版本已变,需重试或报错
- 注意:version 字段必须为整型且初始值非空(如 0 或 1),不能用默认 NULL;更新时 version 必须自增,不可直接赋值
- 适合订单状态流转、用户资料轻量编辑等操作;不适合高频争抢(如秒杀库存扣减),重试成本高
悲观锁:适合写多、冲突明确、需强一致性的短事务
依赖数据库行级锁(如 SELECT ... FOR UPDATE),在查询阶段就锁定记录,阻塞其他写操作,直到事务结束。
本文档主要讲述的是基于VC与Matlab的混合编程实现图像的三维显示;介绍了VC++与Matlab混合编程的一般实现方法,并实现对二维影像图的三维效果显示。 MATLAB既是一种直观、高效的计算机语言,同时又是一个科学计算平台。它为数据分析和数据可视化、算法和应用程序开发提供了最核心的数学和高级图形工具。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
- 必须在事务内使用:BEGIN; SELECT * FROM inventory WHERE sku = 'A001' FOR UPDATE; UPDATE inventory SET stock = stock - 1 WHERE sku = 'A001'; COMMIT;
- 注意:FOR UPDATE 只在可重复读(RR)隔离级别下真正生效;若查询条件未命中索引,可能升级为表锁,引发性能雪崩
- 适合银行转账、库存预占、活动名额锁定等强一致性要求场景;但要严控事务粒度,避免长事务持锁
混合策略:用乐观锁兜底,悲观锁保关键路径
单一锁机制难覆盖所有边界。实际系统常分层处理:前端/服务层用乐观锁做快速校验,核心资源层用悲观锁兜底防超卖。
- 例如秒杀:先用 Redis 原子计数器限流 + 版本号校验订单状态;库存扣减时再进 DB 执行 SELECT ... FOR UPDATE 精确锁行
- 避免“伪乐观”:不要只在应用层比对内存对象版本,必须让 version 校验落到数据库 WHERE 条件中,否则无并发保护力
- 日志与监控要覆盖锁失败路径(如 version 不匹配、FOR UPDATE 超时),便于定位重试风暴或死锁风险
避坑要点:锁失效的常见原因
很多锁没起作用,不是逻辑错,而是细节漏了。
- 事务未开启或自动提交开着(autocommit=1),FOR UPDATE 立即释放,形同虚设
- WHERE 条件用了非唯一索引或无索引字段,MySQL 可能锁住多个无关行,甚至锁表
- 乐观锁 version 字段被 ORM 框架自动忽略更新(如 MyBatis 的 @Select 注解未配 @Options(useGeneratedKeys=true)),导致始终为旧值
- 跨库/分表场景下,单库乐观锁无法保证全局一致性,需引入分布式锁或 TCC 补偿









