You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何EntityManager#flush会引发LockAcquisitionException?

问题分析:Hibernate flush时触发LockAcquisitionException的原因

问题场景

项目基于Hibernate作为持久化框架,在@Transactional事务边界内,通过Spring Data JPA Repository的@Lock(LockModeType.PESSIMISTIC_WRITE)(对应SQL的FOR UPDATE)查询并锁定最多10条数据,更新实体后调用flush()方法时触发LockAcquisitionException,且仅在高并发时段复现。

代码示例

@Transactional
public void method() {
    // 使用@Lock(LockModeType.PESSIMISTIC_WRITE)锁定数据
    List<Foo> entities = fooRepository.selectForUpdate();
    // 遍历实体并执行更新操作
    for (Foo foo : entities) {
        foo.setX(321);
    }

    // 保存实体列表
    fooRepository.saveAll(entities);
    // flush() 触发LockAcquisitionException
    fooRepository.flush();
}

异常堆栈(关键片段)

org.springframework.dao.CannotAcquireLockException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.LockAcquisitionException: could not execute statement
...
at com.sun.proxy.$Proxy150.flush(Unknown Source)
at xxx.xxx.xxx.xxx.MyClass.method(MyClass.java:764)

核心原因

  • 悲观锁的并发冲突:@Lock(LockModeType.PESSIMISTIC_WRITE)对应的FOR UPDATE锁在查询时获取,持有至事务结束。高并发下,其他线程可能在当前事务的查询到flush阶段,尝试获取同批数据的锁,若锁等待超时则触发异常。
  • 冗余操作引发缓存混乱:查询出的Foo实体处于Hibernate的托管状态,事务内的属性变更会被自动跟踪,手动调用saveAll属于冗余操作,可能导致Hibernate缓存状态异常,flush时生成额外SQL,扩大锁冲突范围。
  • 行锁升级或更新范围不一致:若selectForUpdate()的查询条件未使用有效索引,数据库可能将行锁升级为表锁,大幅提升并发冲突概率;另外,若flush时更新的行超出selectForUpdate()锁定的范围(如缓存中存在未被锁定的Foo实体),会尝试获取新锁,高并发下易失败。
  • 数据库锁超时设置过短:数据库的锁等待超时阈值(如MySQL的innodb_lock_wait_timeout)设置过短,高并发下事务执行时间超过阈值时,flush阶段的SQL执行会触发超时。

解决建议

  • 移除冗余的saveAll调用:托管状态的实体变更无需手动保存,Hibernate会在事务提交时自动同步,减少缓存操作和不必要的SQL生成,降低锁冲突风险。
  • 确保查询与更新的行范围一致:检查业务逻辑,保证selectForUpdate()锁定的行与后续修改的行完全匹配,避免flush时更新未被锁定的实体。
  • 优化数据库索引与锁配置:为selectForUpdate()的查询条件添加有效索引,避免行锁升级;适当调整数据库锁等待超时时间,平衡并发性能与死锁风险。
  • 显式设置锁超时:在@Lock注解中指定超时参数,如@Lock(value = LockModeType.PESSIMISTIC_WRITE, timeout = 5000),明确锁等待时长,避免无限等待。

内容的提问来源于stack exchange,提问作者Matheus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 22:35:37