java - 使用 Postgres 在 Spring Data JPA 中的事务中发出脏读

标签 java spring postgresql hibernate jpa

我很惊讶 PostgreSQL 在 9.6 中删除了脏读(读取未提交的隔离级别)( https://www.postgresql.org/docs/9.6/static/transaction-iso.html ,但它至少在 9.1 https://www.postgresql.org/docs/9.1/static/transaction-iso.html 中得到支持)。

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

  • 使用 findById() 检查实体是否存在
  • 如果没有则保存()一个新实体

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

那么,当前标准如何解决这个问题,我们真的应该搞乱同步吗?将 AlreadyExistsException 视为控制流,并在我们复制流程时损失性能?

最佳答案

mvcc 从不支持脏读。但我可以看到早在 8.0 的文档中就清楚地说明了这一点:

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

In PostgreSQL, you can request any of the four standard transaction isolation levels. But internally, there are only two distinct isolation levels, which correspond to the levels Read Committed and Serializable. When you select the level Read Uncommitted you really get Read Committed

从 9.1 Repeatable read 添加:

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

In PostgreSQL, you can request any of the four standard transaction isolation levels. But internally, there are only three distinct isolation levels, which correspond to the levels Read Committed, Repeatable Read, and Serializable. When you select the level Read Uncommitted you really get Read Committed

更新 正如 a_horse_with_no_name 注意到的那样 - 在内部,从 7.1 开始只有两个不同的隔离级别:

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

Postgres offers the read committed and serializable isolation levels.

感谢@Laurenz 的另一个说明:

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

Prior to PostgreSQL version 9.1, a request for the Serializable transaction isolation level provided exactly the same behavior described here (REPEATABLE READ). To retain the legacy Serializable behavior, Repeatable Read should now be requested.

或者只是引用@Laurenz 自己的话:

In 9.1, the old SERIALIZABLE was renamed to REPEATABLE READ because it did not guarantee that there is an equivalent serialized execution order. In the same release, "real" SERIALIZABLE was added, which is something quite different.

关于java - 使用 Postgres 在 Spring Data JPA 中的事务中发出脏读,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47831835/

相关文章:

sql - 使用 PostgreSQL 选择一棵树并对 child 进行排序

java - 使用 Commons Configuration 在数据库中存储属性

java - 用spring配置集群hornetq客户端

java - 我可以让 Eclipse 源格式化程序保留运算符周围的原始间距吗?

java - 在 TreeMap 中搜索 (Java)

java - 找不到 Integer.parseInt() 的符号错误

angularjs - Spring REST 调用提供 302 重定向

java - 是否可以注入(inject)Spring配置方法?

arrays - 用其他表的值填充数组的值

java - 将所需变量传递给所有代码的最佳设计模式,无需