使用REPEATABLE READ保证speciifc值的唯一性

时间:2018-05-28 10:39:59

标签: database spring postgresql isolation-level

我们有一个简单的表格:

Human:
+------+
|Height|
+------+
|      |
+------+

我有一个添加人类的方法:

@AutoWired 
HumanRepository humanRepo; // JpaRepository

@Transactional(isolationLevel = REPEATABLE_READ)
void addHuman(int height){
    if(humanRepo.existsByHeight(height){
      throw new HumanWithSuchHeightExists();
    }
    humanRepo.save(Human.builder().height(height).build())
}

我想保证只存在一个具有特定身高的男人。

  1. REPEATABLE_READ能保证吗?
  2. 我的代码(伪代码)是否正确以满足该条件?

2 个答案:

答案 0 :(得分:1)

理论说唯一能够绝对保证的等值水平。数据完整性(wrt声明的规则)是SERIALIZABLE。

使用REPEATABLE READ,理论上你仍然面临两个事务试图插入同一行的风险,以及允许传递的以下事件序列:

T1检查存在行,行不存在
T2检查存在行,行不存在
T1插入,可能重复行的存在检查(仍然不存在)
T2插入,可能重复行的存在检查(仍然“不存在”,因为T1尚未提交,因此其新插入的数据对T2保持不可见)。
T1承诺
T2提交

REPEATABLE READ,正如名称所述,仅提供与现有行相关的保证(即如果发现存在行,则不会被更改通过其他交易,然后读取变得“可重复”)。

答案 1 :(得分:0)

是的,PostgreSQL SERIALIZABLE应该防止创建多个具有相同高度的记录。它将中止T1或T2。

我认为该异常现象被正式称为“反依赖性周期”(G2)。这是good reference that includes major databases

此外,为什么不使用unique constraint呢?