DB2中的事务隔离ANSI REPEATABLE_READ未按预期锁定行

时间:2018-06-15 13:35:55

标签: spring-transactions db2-400 isolation-level pessimistic-locking

我遇到了DB2隔离级别的情况,我无法解释。

我有一个隔离级别为REPEATABLE_READ的事务,它在DB2中对应于READ_STABILITY。

我对DB2 S-,U-和X-lock有基本的了解。

当我在parallell中执行以下Spring事务时,我可能会导致死锁(DB2中的错误是FILE IN USE):

@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
public long getNext(int x) {
    final Stuff stuff = entityManager
            .createQuery("from Stuff where type = :type", Stuff.class)
            .setParameter("cardType", cardType)
            .getSingleResult();

    stuff.setData(stuff.getData() + x);
    return stuff.getData()+1;
}

我希望REPEATABLE_READ隔离会在返回的行上设置DB2 U锁定,以便并行事务排队等待。

相反,为了让它工作,我需要添加一个悲观的写锁:

@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
public long getNext(int x) {
    final Stuff stuff = entityManager
            .createQuery("from Stuff where type = :type", Stuff.class)
            .setParameter("cardType", cardType)
            .setLockMode(LockModeType.PESSIMISTIC_WRITE)
            .getSingleResult();


    stuff.setData(stuff.getData() + x);
    return stuff.getData()+1;
}

上面的查询生成正确的锁定SQL和事务没有死锁:

select * from .... for update with rs;

问题是,为什么在我还需要手动锁定时使用REPEATABLE_READ?我的理解是REPEATABLE_READ必须自己处理必要的行锁定以确保可重复读取。

1 个答案:

答案 0 :(得分:0)

i的Db2支持可重复读取(RR)和读取稳定性(RS)。

Repeatable Read

  

在SQL 2003 Core标准中,Repeatable Read被称为Serializable   Db2®fori支持可重复读取COMMIT(* RR)。通过锁定包含任何读取或更新行的表来支持可重复读隔离级别。

可重复读取是最高级别的隔离。

如果你只想锁定你触摸的行,我想你想要读稳定性(RS)。这是一个降级。差异是RS允许phantom reads

  

幻影。工作单元UW1读取满足某些搜索条件的n行集。然后,工作单元UW2插入满足搜索条件的一行或多行。然后,UW1以相同的搜索条件重复初始读取,并获得原始行和插入的行。