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

Spring Data JPA悲观锁未按预期工作,求问题排查

问题分析与解决方案

核心原因

你遇到的could not serialize access due to concurrent update错误,根源是事务隔离级别与悲观锁的逻辑冲突:

  • 服务层设置的Isolation.SERIALIZABLE(序列化隔离级别)是PostgreSQL最严格的隔离级别,该级别下PostgreSQL采用「快照隔离+并发冲突检测」机制,不会阻塞等待锁释放,一旦检测到并发修改就直接抛出序列化失败错误并回滚事务,完全覆盖了悲观锁的阻塞等待逻辑。
  • 仓库层的@Lock(LockModeType.PESSIMISTIC_WRITE)虽声明了悲观写锁,但在SERIALIZABLE隔离级别下无法生效。

修复步骤

1. 调整事务隔离级别

将服务层的事务隔离级别改为PostgreSQL默认的REPEATABLE_READ(或更低的READ_COMMITTED),让悲观锁的阻塞逻辑正常工作:

@Transactional(isolation = Isolation.REPEATABLE_READ)
@Override
public void processWithPessimisticLock() {
   fiveEntityRepository.addToSequence(lastId);
}

2. 优化仓库层代码

entityManager.find加载的实体属于托管状态,事务提交时JPA会自动同步修改到数据库,无需额外调用merge:

@Lock(LockModeType.PESSIMISTIC_WRITE)
@Override
public void addToSequence(Integer id) {
    FiveEntity fiveEntity = entityManager.find(FiveEntity.class, id);
    fiveEntity.setSequence(fiveEntity.getSequence() + 1);
    log.debug("sequence: {}", fiveEntity.getSequence());
    // 移除多余的entityManager.merge(fiveEntity);
}

额外说明

如果业务确实需要SERIALIZABLE隔离级别,那么必须处理序列化失败的重试逻辑(比如使用Spring的@Retryable注解或手动实现重试),但这会放弃你预期的「阻塞等待锁释放」行为,因此不推荐这种方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 05:20:28