2016-11-14 50 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