Spring 事务隔离级别

4

我们中的大多数人可能正在使用Spring和Hibernate进行数据访问。 我尝试了解一些Spring事务管理器的内部。

根据Spring API,它支持不同的隔离级别 - doc 但我找不到清晰明了的信息,说明在哪些场合下使用这些隔离级别可以真正有助于提高性能。

我知道从Spring TransactionreadOnly参数可以帮助我们使用不同的TxManagers来读取只读数据,并且可以利用良好的性能。但是它会锁定表以获取数据,以避免脏读/未提交读取-doc

假设,在某些情况下,我们可能希望将记录盲目插入表中并检索信息,而不锁定表,即我们永远不会更新表数据,我们只是插入和读取[仅添加]。我们可以使用更好的隔离级别来提高性能吗?

  1. 正如您从其中一个参考链接中看到的那样,我们是否真正需要实现/编写自己的CustomJPADiaelect?
  2. 对于我的要求,哪种隔离级别更好?
2个回答

4

只读允许某些优化,例如禁用脏检查,当您不打算更改实体时应该完全使用它。

每种隔离级别定义了数据库必须施加多少锁来确保数据异常预防。

大多数数据库使用MVCC(Oracle、PostgreSQL、MySQL),因此读者不锁定写者写者不锁定读者。只有写者锁定写者,如以下示例所示。

REPEATABLE_READ不必持有来防止并发事务修改当前事务加载的行。MVCC引擎允许其他事务读取已提交状态的行,即使当前事务已更改但尚未提交(MVCC使用撤销日志还原待处理更改行的前一个版本)。

在您的用例中,应使用READ_COMMITTED,因为它比其他严格的隔离级别更为高效,您应该使用乐观锁定来防止长时间会话中的丢失更新。


更新

@Transactional(isolation = Isolation.SERIALIZABLE)设置到Spring bean中有不同的行为,具体取决于当前事务类型:

  • 对于RESOURCE_LOCAL事务,JpaTransactionManager可以为当前运行的事务应用特定的隔离级别。
  • 对于JTA资源,事务范围的隔离级别不会传播到底层数据库连接,因为这是默认的JTA事务管理器行为。您可以覆盖此行为,参考WebLogicJtaTransactionManager的示例。

1
在发布这篇文章之前,我也阅读了你的博客。但是我们真的需要实现自己的JPADialect来实现这个吗? - RaceBase
请发送链接,我不明白你在指什么。 - Vlad Mihalcea
1
对于JPA,隔离级别可以从@Transaction中正确获取。如果您使用JTA,需要一些解决方法,因为JTA标准不支持它。 - Vlad Mihalcea
对于 Stack Overflow 的用户,您能否详细解释一下使用不同隔离级别和示例用例的答案。这将对许多用户有所帮助。 - RaceBase
@VladMihalcea,请帮忙查看一下我的帖子:http://stackoverflow.com/questions/32114750/spring-transaction-by-connecting-to-multiple-databases。 - learner
显示剩余4条评论

2

实际上,readOnly=true 不会导致数据库表发生任何锁争用,因为没有必要进行任何锁定 - 数据库能够忽略所有新更改并返回到之前记录的版本。

将 readOnly 设置为 true 后,在当前 Hibernate 会话中,你的 flush 模式将是 FlushMode.NEVER,阻止会话提交事务。此外,setReadOnly(true) 将在 JDBC 连接上调用,这也是对底层数据库不提交更改的提示。

所以,readOnly=true 正是你需要的(例如,SERIALIZED 隔离级别)。

这里有一个很好的解释。


我可能会同意 readOnly 部分。那么关于写入 (writes) 呢?在这种情况下,我们可以使用任何特定的隔离级别吗? - RaceBase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接