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

MVCC模式下HSQLDB执行SELECT ... FOR UPDATE未锁行,是否支持悲观行锁?

HSQLDB悲观锁不生效问题解答

HSQLDB 2.6.1是否支持悲观行锁

HSQLDB 2.0及以上版本(包含你使用的2.6.1版本)支持悲观行锁,你遇到的多线程同时获取锁的问题,是MVCC并发控制模型的默认配置导致的,和代码实现无关。
默认MVCC模式下,HSQLDB的SELECT ... FOR UPDATE语句不会对查询到的行加排他锁,而是直接读取最新提交的行快照,因此多个事务可以同时获取到查询结果,不会出现预期的阻塞排队效果。

解决方案

  • 方案1:开启MVCC模式下的FOR UPDATE锁配置
    在HSQLDB的连接参数、数据库配置文件或者启动参数中添加配置项hsqldb.lock.forupdate=true。开启该配置后,MVCC模式下的SELECT ... FOR UPDATE语句会对匹配行加排他锁,其他事务查询同一条数据时会被阻塞,直到持有锁的事务提交或回滚,完全符合悲观锁的预期逻辑,同时可以保留MVCC模式的高并发性能。
  • 方案2:切换并发控制模型为两阶段锁(2PL)
    将HSQLDB的事务控制模式配置修改为hsqldb.tx=locks,该模式下读写操作都会加锁,天然支持悲观行锁的阻塞逻辑,无需额外配置其他参数。不过2PL模式的并发性能低于MVCC模式,更适合对并发要求不高的测试场景使用。
  • 方案3:验证事务边界正确性
    你当前的代码配置了@Transactional(propagation = Propagation.REQUIRES_NEW),需要确认该方法被Spring AOP正确代理,每个调用确实开启了独立事务。可以添加日志打印当前事务标识验证:
    // 引入Spring事务工具类
    import org.springframework.transaction.support.TransactionSynchronizationManager;
    
    public void sync() {
        // 打印当前事务名称,确认每个线程事务独立
        log.debug("current transaction: {}", TransactionSynchronizationManager.getCurrentTransactionName());
        MyEntity entity = entityManager.find(MyEntity.class, entityId, LockModeType.PESSIMISTIC_WRITE);
        log.debug("entity {} was locked", entity.getKey());
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 01:54:06