使用Postgres在Spring Data JPA中的事务中发出Dirty Reads

时间:2017-12-15 11:52:30

标签: java spring postgresql hibernate jpa

我很惊讶PostgreSQL在9.6(https://www.postgresql.org/docs/9.6/static/transaction-iso.html中删除了Dirty Reads(Read Uncommited Isolation Level),但它至少支持9.1 https://www.postgresql.org/docs/9.1/static/transaction-iso.html。)

现在,我的问题是执行以下操作的控制器方法:

  • 使用findById()
  • 检查实体是否存在
  • 如果不是
  • ,则保存()新实体

所以我把方法包装在@Transactional(readOnly = false, isolation_level = READ_UNCOMMITED)中,这就是让我意识到隔离不起作用的原因,因为第二个线程/事务即使它被创建了也没有找到id第一个以防止两个事务都没有提交,因此,代码会尝试两次插入id。

那么,如果我们真的搞乱同步,怎么能用现行标准解决呢?将AlreadyExistsException视为控制流,并在复制流程时失去性能?

1 个答案:

答案 0 :(得分:1)

mvcc从不支持脏读。但是我可以在早在8.0的文档中清楚地看到它:

https://www.postgresql.org/docs/8.0/static/transaction-iso.html

  

在PostgreSQL中,您可以请求任何四种标准交易   隔离级别。但在内部,只有两个截然不同   隔离级别,对应于Read Committed和   序列化。当你选择级别Read Uncommitted时,你真的   获得Read Committed

并从9.1 Repeatable read添加:

https://www.postgresql.org/docs/9.1/static/transaction-iso.html

  

在PostgreSQL中,您可以请求任何四种标准交易   隔离级别。但在内部,只有三个不同   隔离级别,对应于Read Committed,   可重复读取和可序列化。选择级别Read时   未提交你真的得到Read Committed

<强>更新 作为a_horse_with_no_name注意到 - 在内部,从7.1开始只有两个不同的隔离级别:

https://www.postgresql.org/docs/7.1/static/transaction-iso.html

  

Postgres提供读取已提交和可序列化的隔离级别。

感谢@Laurenz的另一个注意事项:

https://www.postgresql.org/docs/current/static/transaction-iso.html

  

在PostgreSQL版本9.1之前,对Serializable的请求   事务隔离级别提供了完全相同的行为   这里描述(REPEATABLE READ)。要保留旧的Serializable行为,可重复   现在应该要求阅读。

或只是引用@Laurenz本人:

  

在9.1中,旧的SERIALIZABLE被重命名为REPEATABLE READ,因为它   不保证有等效的序列化执行   订购。在同一版本中,添加了“真正的”SERIALIZABLE,即   一些完全不同的东西。