LockModeType.OPTIMISTIC与MySQL默认REPEATABLE READ是否不兼容?
Hibernate乐观锁与MySQL RR隔离级别兼容性解答
核心结论
LockModeType.OPTIMISTIC完全可以和MySQL默认的REPEATABLE READ(可重复读)隔离级别正常配合工作,你所担忧的冲突问题不存在,该误解来源于对两个组件的实现细节认知不全面。
认知偏差修正
1. MySQL RR隔离级别的读行为差异
你提到的「同一事务内一致性读复用首次快照」仅适用于普通无锁SELECT(快照读),以下操作都属于「当前读」,会直接读取最新的已提交数据,不受快照限制:
- 加锁读:
SELECT ... FOR UPDATE/SELECT ... FOR SHARE - 写操作:
UPDATE/DELETE/INSERT
2. Hibernate乐观锁的校验逻辑
LockModeType.OPTIMISTIC的版本校验逻辑完全基于当前读实现,根本不会用到普通快照读,不存在读取旧版本的可能:
- 若事务内修改了实体:最终执行的UPDATE语句会自动携带版本匹配条件,格式为
UPDATE item SET [字段列表], version = version + 1 WHERE id = ? AND version = ?,此处UPDATE属于写操作即当前读,若其他事务已将版本更新为1,该语句影响行数为0,Hibernate会直接抛出OptimisticLockException。 - 若事务内实体为只读:Hibernate在提交前的版本校验会发送加锁的SELECT语句
SELECT version FROM item WHERE id = ? FOR SHARE,该语句属于当前读,会直接读取到最新的版本号,和实体缓存的旧版本对比不一致时就会抛出异常,根本不会复用事务开头的快照。
示例代码运行结果
你给出的代码运行时,无论事务是否修改了Item实体,都会正确捕获到其他事务的版本更新,抛出预期的OptimisticLockException,不会出现你担心的校验失效问题。
注:仅当你自定义修改了Hibernate的默认校验逻辑,改用无锁SELECT做版本校验时,才会出现校验失效的问题,官方默认实现不存在该缺陷。
内容的提问来源于stack exchange,提问作者Curry
相关产品推荐
相关产品推荐

