我遇到了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必须自己处理必要的行锁定以确保可重复读取。
答案 0 :(得分:0)
i的Db2支持可重复读取(RR)和读取稳定性(RS)。
在SQL 2003 Core标准中,Repeatable Read被称为Serializable Db2®fori支持可重复读取COMMIT(* RR)。通过锁定包含任何读取或更新行的表来支持可重复读隔离级别。
可重复读取是最高级别的隔离。
如果你只想锁定你触摸的行,我想你想要读稳定性(RS)。这是一个降级。差异是RS允许phantom reads
幻影。工作单元UW1读取满足某些搜索条件的n行集。然后,工作单元UW2插入满足搜索条件的一行或多行。然后,UW1以相同的搜索条件重复初始读取,并获得原始行和插入的行。