Hibernate 髒資料檢查機制與資料快取
一. 髒資料檢查機制
髒資料: 髒資料並非廢棄或者無用的資料,而是指一個數據物件所攜帶的資訊發生了改變之後的狀態.
如果我們從資料庫中讀取一個物件,事務提交時 Hibernate會對session 中的PO進行檢測,判斷哪些發生了變化,並將發生變化的資料更新到資料庫中.
Hibernate如何判斷一個數據物件是否發生了改變,或者說 Hibernate 如何進行髒資料識別?
髒資料檢查的一般策略大致有下面兩種:
1.資料物件監控
資料物件監控的實現方式,大體上是通過攔截器對資料物件的設值方法 (setter) 進行攔截,攔截器的實現可以藉助Dynamic Proxy 或者 CGlib 實現.一旦資料物件的設定方法被呼叫(通常這也就意味著資料物件的內容發生變化),則將其標誌為"待更新"狀態,之後在資料庫操作時將其更新到資料庫中.
2.資料版本比對
在持久層框架中維持資料物件的最近讀取版本,當資料提交時將提交資料與此版本進行比對,如果發生變化則將其同步到資料庫中.
Hibernate採取的是第二種檢查策略
二. 資料快取
一般而言,ORM 的資料快取應包含如下幾個層次:
1.事務級快取
在當前事務範圍內的資料快取策略.
這裡的事務可能是一個數據庫事務,也可能是某個應用級事務.對於Hibernate而言,事務級快取是基於Session 生命週期實現的,每個Session 會在內部維持一個數據快取,此快取隨著Session 的建立(銷燬)而存在(消亡),因此也稱為Session Level Cache(也稱為內部快取)
2.應用級/程序級快取
在某個應用,或者應用中某個獨立資料訪問子集中的共享快取.
此快取可由多個事務(資料庫事務或者應用級事務)共享.事務之間的快取共享策略與應用的事務隔離機制密切相關.在Hibernate中,應用級快取在SessionFactory層實現,所有由此SessionFactory 建立的Session 例項共享此快取,因此也稱為SessionFactory Level Cache.
多例項併發執行的環境(如多機負載均衡環境中),我們必須特別小心快取機制可能帶來的負面效應.
假設例項A 和例項B 共享同一資料庫,並行執行,A和B各自維持自己的快取,如果缺乏同步機制,A在某個操作中對資料庫進行了更新,而B並沒有獲得相應的更新通知,其快取中的資料還是資料庫修改之前的版本,那行B在之後的讀取操作中,可能就以此過期資料作為資料來源,從而導致資料同步錯誤,這樣的錯誤對於關鍵業務資料而言是無法承擔的(如賬務系統)
在這種情況下,應用級快取無法使用,為了解決這個問題,我們引入了分散式快取.
3.分散式快取
在多個應用例項,多個JVM之間共享的快取模式.
分散式快取由多個應用級快取例項組成叢集,通過某種遠端機制(如RMI或JMS)實現各個快取例項間的資料同步,任何一個例項的資料修改操作,將導致整個叢集間的資料狀態同步.
分散式快取解決了多例項併發執行過程中的資料同步問題.
但是,除非對於併發讀取效能要求較高,且讀取操作在持久層操作中佔絕大部分比重的情況,分散式快取的實際效果尚需考證.
由於多個例項間的資料同步機制,每個快取例項發生的變動都會複製到其餘所有節點中(對於Repplication 式快取而言),這樣的遠端同步開銷不可忽視.