2016-11-14 88 views
0

在我的服务类(被注释为交易),我更新,然后保存对象为:休眠拿到后刷新数据提交之前

myObj.save(flush:true) //(Thread A, updates the value, Step A) 

在此之后,数据的处理发生这需要很长时间。在这个处理过程中,在域类中进行了很多更改,但这些更改在这里不相关。由于所有这些处理都发生在同一个服务类中,因此它是单个事务的一部分。

现在,在此期间,当所有这些处理是怎么回事,另一个线程,这是一个不同的休眠会话的一部分,访问

MyObj.findAll() //Thread B,并在结果集我看到更新后的值。在Step A中更新的值但是,线程A尚未完成,因此更改尚未提交到数据库。我可以证实这一点,因为如果我直接在mysql workbench中运行查询,那么我没有看到更改。仅当通过休眠访问对象时才会显示更改。

我的印象是,如果由于刷新而进行更改,那么这些更改在同一个事务中可见,而在其他事务中不可见。有人可以澄清?

回答

1

答案是这取决于mysql服务器中使用的隔离级别。作为innodb transaction isolation levels MySQL文档说:

的隔离级别是当多个事务进行更改,并在执行 的查询微调之间 的性能和可靠性,一致性和 结果重现性的平衡设定同时。

的InnoDB提供由 SQL描述的所有四个事务隔离级别:1992标准:未提交读,读取提交,可重复读, 和序列化。 InnoDB的默认隔离级别是REPEATABLE READ。

该文档详细描述了各个层次之间的差异。我想提请你注意特别是对未提交读级别:

SELECT语句以非锁定方式进行,但可以使用一排的 可能的早期版本。因此,使用这种隔离级别,这样的读取并不一致。这也被称为 脏读。否则,这个隔离级别就像READ COMMITTED一样。

此隔离级别使查询能够读取其他事务更新的数据,这些事务尚未提交。但是,在代码中使用此隔离级别之前,请确保您了解此隔离级别的所有影响。您无法挑选哪些交易中您想要查看的未公开数据。所以,您可以选择稍等一会儿来获取提交的数据。

+0

感谢您的解释,它确实有帮助。但是,当我使用查询“select @@ GLOBAL.tx_isolation,@@ tx_isolation;”检查MySQL中的隔离级别时它显示'REPEATABLE-READ'。 我会调查hibernate是否设置了一些隔离级别,虽然它不应该是这样,但我仍然会试图找出答案。任何其他想法/解释为什么它可能发生,因为隔离级别是可重复读取。 – Zohaib

+0

正如你从答案中的第一句话中可以看到的那样,''InnoDB的默认隔离级别是REPEATABLE READ。''根据我的经验,ORM很少设置隔离级别,他们只是使用任何设置。 – Shadow

+0

是的,这也是我所假设的。 Hibernate绝对不会设置隔离级别。这就是为什么原始的根本原因仍然未知。感谢您的时间,让我知道是否还有其他事情我应该调查以找出为什么线程B在threadA尚未完成时读取更新。 – Zohaib