0

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

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

我对 DB2 S-、U-和 X-locks 有基本的了解。

当我并行执行以下 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 必须自己处理必要的行锁定以确保可重复读取。

4

1 回答 1

0

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

可重复读取

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

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

如果您只想锁定您触摸的行,我认为您需要读取稳定性(RS)。这是一个下降。不同之处在于 RS 允许幻读

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

于 2018-06-15T17:25:22.663 回答