主題:   最近在看Hibernate的緩存,有一點沒搞清楚

精華帖 (0) :: 良好帖 (0) :: 入門帖 (13) :: 隱藏帖 (0) 
作者 正文
ellie4c
等級: 初級會員
ellie4c的博客:ellie4c

文章: 20
積分: 27
圈子: Tapestry

       時間: 2007-06-01 15:18    關鍵字:   Hibernate           

我想問一下,hibernate在事務提交后一級緩存的實例是如何和二級緩存同步的?用到那些機制哪?










聲明:JavaEye文章版權屬于作者,受法律保護。沒有作者書面許可不得轉載。若作者同意轉載,必須以超鏈接形式標明文章原始出處和作者。

相關文章:   對robbin所說Hibernate缺陷的一些不理解   Hibernate中如何通過父節點查詢所有子節點?

推薦鏈接:   免費下載IBM社區版軟件,體驗高效開發.   京滬穗蓉四地免費注冊,SOA技術高手匯聚交鋒.
返回頂端  1樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 15:18  
alex22222
等級: 初級會員
alex22222的博客:alex22222

文章: 3
積分: 4

       時間: 2007-06-01 15:20    評級:   11111 (0位會員評分)          

這個問題我也想搞清楚

返回頂端  2樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 15:20   我來評分:  請先 登錄
ahuaxuan
等級: 2鉆會員
ahuaxuan的博客:ahuaxuan

性別:
文章: 499
積分: 1156
來自: 上海
圈子: JBPM @net

       時間: 2007-06-01 15:34    評級:   11111 (0位會員評分)          

事務提交后,一級緩存中的數據會被更新到數據庫,如果二級緩存設置為讀寫,那么這份數據會同時更新到二級緩存。
你問的問題相當于:事務提交后一級緩存中的數據怎么同步到數據庫。

返回頂端  3樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 15:34  
我來評分:  請先 登錄
ellie4c
等級: 初級會員
ellie4c的博客:ellie4c

文章: 20
積分: 27
圈子: Tapestry

       時間: 2007-06-01 15:41    評級:   11111 (0位會員評分)          

不是的 一級緩存的數據,其實在h執行相關的save,insert的時候已經提交到數據庫的臟數據里面了。
我想問的是一級緩存是利用什么機制 來同步二級緩存的,有誰知道嗎?

返回頂端  4樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 15:41  
我來評分:  請先 登錄
拋出異常的愛
等級: 5鉆會員
拋出異常的愛的博客:天使不喜歡看代碼

文章: 5237
積分: 2512
來自: 北京
圈子: 盤古黨

       時間: 2007-06-01 15:45    評級:   11111 (1位會員評分)          

查詢。
臟了丟掉/

返回頂端  5樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 21:15  
我來評分:  請先 登錄
ahuaxuan
等級: 2鉆會員
ahuaxuan的博客:ahuaxuan

性別:
文章: 499
積分: 1156
來自: 上海
圈子: JBPM @net

       時間: 2007-06-01 15:51    評級:   11111 (0位會員評分)          

ellie4c 寫道
不是的 一級緩存的數據,其實在h執行相關的save,insert的時候已經提交到數據庫的臟數據里面了。
我想問的是一級緩存是利用什么機制 來同步二級緩存的,有誰知道嗎?

你說hibernate在執行save操作時會提交數據到數據庫,你在哪里看到的結論,你用的是什么數據庫,支持事務嗎,你不會用的mysql的myisam吧
返回頂端  6樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 15:51  
我來評分:  請先 登錄
ellie4c
等級: 初級會員
ellie4c的博客:ellie4c

文章: 20
積分: 27
圈子: Tapestry

       時間: 2007-06-01 15:54    評級:   11111 (0位會員評分)          

你的意思是不是指 拿一級緩存的PO去查數據庫,如果返回對象的話則 更新數據庫,如果沒返回則 通知二級緩存 丟掉數據?是不是這樣的?hibernate也是這樣的馬?

返回頂端  7樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 15:54  
我來評分:  請先 登錄
ellie4c
等級: 初級會員
ellie4c的博客:ellie4c

文章: 20
積分: 27
圈子: Tapestry

       時間: 2007-06-01 15:54    評級:   11111 (0位會員評分)          

你的意思是不是指 拿一級緩存的PO去查數據庫,如果返回對象的話則 更新二級緩存,如果沒返回則 通知二級緩存 丟掉數據?是不是這樣的?hibernate也是這樣的馬?

返回頂端  8樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 15:54  
我來評分:  請先 登錄
ellie4c
等級: 初級會員
ellie4c的博客:ellie4c

文章: 20
積分: 27
圈子: Tapestry

       時間: 2007-06-01 15:59    評級:   11111 (0位會員評分)          

ahuaxuan 寫道
ellie4c 寫道
你說hibernate在執行save操作時會提交數據到數據庫,你在哪里看到的結論,你用的是什么數據庫,支持事務嗎,你不會用的mysql的myisam吧

這里的提交是臟提交,是提交到事務本身的數據空間里面,真正的提交是在執行tx.commit

返回頂端  9樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 15:59  
我來評分:  請先 登錄
ahuaxuan
等級: 2鉆會員
ahuaxuan的博客:ahuaxuan

性別:
文章: 499
積分: 1156
來自: 上海
圈子: JBPM @net

       時間: 2007-06-01 16:00    評級:   11111 (0位會員評分)          

ellie4c 寫道
你的意思是不是指 拿一級緩存的PO去查數據庫,如果返回對象的話則 更新二級緩存,如果沒返回則 通知二級緩存 丟掉數據?是不是這樣的?hibernate也是這樣的馬?

第一,如果你的數據庫支持事務,而且默認隔離級別是讀寫已提交的話(大部分數據庫是這樣),是不會出現什么臟數據的。可以仔細閱讀一下事務和隔離級別,和不同隔離級別所能解決的情況。讀寫已提交就是解決臟讀問題的
第二,一級緩存中存放的就是持久對象,那為什么要查數據庫呢,看來你對hibernate管理的對象的3種狀態理解不深刻,持久狀態的對象就代表數據庫中的記錄




主題:   最近在看Hibernate的緩存,有一點沒搞清楚

精華帖 (0) :: 良好帖 (0) :: 入門帖 (13) :: 隱藏帖 (0) 
作者 正文
ellie4c
等級: 初級會員
ellie4c的博客:ellie4c

文章: 20
積分: 27
圈子: Tapestry

       時間: 2007-06-01 16:12    評級:   11111 (0位會員評分)          

[quote="ahuaxuan第一,如果你的數據庫支持事務,而且默認隔離級別是讀寫已提交的話(大部分數據庫是這樣),是不會出現什么臟數據的。可以仔細閱讀一下事務和隔離級別,和不同隔離級別所能解決的情況。讀寫已提交就是解決臟讀問題的

這個我很清楚地,你大概沒搞清楚我的問題,這個算了,
我想問你,事務里面的一二級緩存是怎么實現同步的,比如事務里面更新了一個對象,h什么時候通知二級緩存同步對象的狀態,以及h是怎么知道什么時候更新二級緩存,什么時候從二級里面刪除數據

返回頂端  11樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 16:12  
我來評分:  請先 登錄
ahuaxuan
等級: 2鉆會員
ahuaxuan的博客:ahuaxuan

性別:
文章: 499
積分: 1156
來自: 上海
圈子: JBPM @net

       時間: 2007-06-01 16:22    評級:   11111 (0位會員評分)          

ellie4c 寫道

這個我很清楚地,你大概沒搞清楚我的問題,這個算了,
我想問你,事務里面的一二級緩存是怎么實現同步的,比如事務里面更新了一個對象,h什么時候通知二級緩存同步對象的狀態,以及h是怎么知道什么時候更新二級緩存,什么時候從二級里面刪除數據

1,之前你說的有一個臟提交的概念,這個我不知道你是什么意思,你是指發送sql語句給數據庫嗎。
但是調用save方法并不會發送sql語句到db,除非你再調用flush方法。

2,我說了:什么時候把數據同步到數據庫,什么時候就把數據同步到二級緩存。

返回頂端  12樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 16:23  
我來評分:  請先 登錄
ellie4c
等級: 初級會員
ellie4c的博客:ellie4c

文章: 20
積分: 27
圈子: Tapestry

       時間: 2007-06-01 16:27    評級:   11111 (0位會員評分)          

ahuaxuan 寫道
ellie4c 寫道

這個我很清楚地,你大概沒搞清楚我的問題,這個算了,
我想問你,事務里面的一二級緩存是怎么實現同步的,比如事務里面更新了一個對象,h什么時候通知二級緩存同步對象的狀態,以及h是怎么知道什么時候更新二級緩存,什么時候從二級里面刪除數據

1,之前你說的有一個臟提交的概念,這個我不知道你是什么意思,你是指發送sql語句給數據庫嗎。
但是調用save方法并不會發送sql語句到db,除非你再調用flush方法。

2,我說了:什么時候把數據同步到數據庫,什么時候就把數據同步到二級緩存。

怎么同步法?我想知道的是算法,一級緩存里面有一堆對象,怎么通知二級緩存取去執行更新或刪除?
返回頂端  13樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 16:27  
我來評分:  請先 登錄
ellie4c
等級: 初級會員
ellie4c的博客:ellie4c

文章: 20
積分: 27
圈子: Tapestry

       時間: 2007-06-01 16:29    評級:   11111 (0位會員評分)          

ellie4c 寫道
ahuaxuan 寫道
ellie4c 寫道

這個我很清楚地,你大概沒搞清楚我的問題,這個算了,
我想問你,事務里面的一二級緩存是怎么實現同步的,比如事務里面更新了一個對象,h什么時候通知二級緩存同步對象的狀態,以及h是怎么知道什么時候更新二級緩存,什么時候從二級里面刪除數據

1,之前你說的有一個臟提交的概念,這個我不知道你是什么意思,你是指發送sql語句給數據庫嗎。
但是調用save方法并不會發送sql語句到db,除非你再調用flush方法。

2,我說了:什么時候把數據同步到數據庫,什么時候就把數據同步到二級緩存。

怎么同步法?我想知道的是算法,一級緩存里面有一堆對象,怎么通知二級緩存取去執行更新或刪除?
講的詳細點就是 怎么讓二級緩存知道,一級緩存里面的這個對象我應該更新,那個對象我應該刪除?
返回頂端  14樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 16:30  
我來評分:  請先 登錄
ahuaxuan
等級: 2鉆會員
ahuaxuan的博客:ahuaxuan

性別:
文章: 499
積分: 1156
來自: 上海
圈子: JBPM @net

       時間: 2007-06-01 16:41    評級:   11111 (0位會員評分)          

我 的理解是在事務提交的時候,首先在二級緩存中根據id找到對應的數據,然后通過session中的指令來判斷是更新這個數據還是刪除這個數據,通過這樣的 方法,同步了二級緩存之后,再向db發送sql語句,隨后向db發送事務提交指令,但我沒有看過源代碼,應該是類似這樣的

也有可能是在事務提交之后更新二級緩存,這樣也許更合理,因為如果事務回滾,二級緩存就根本都不會涉及到了

返回頂端  15樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 16:51  
我來評分:  請先 登錄
ellie4c
等級: 初級會員
ellie4c的博客:ellie4c

文章: 20
積分: 27
圈子: Tapestry

       時間: 2007-06-01 16:51    評級:   11111 (0位會員評分)          

這樣的話 如果一個對象有多個操作指令的話 比如insert(a),update(a),delete(a)全部在一個事務里面的話,這樣同步起來代價就太大了,不知道其他看過代碼的人 有沒有什么想法

返回頂端  16樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 16:51  
我來評分:  請先 登錄
ahuaxuan
等級: 2鉆會員
ahuaxuan的博客:ahuaxuan

性別:
文章: 499
積分: 1156
來自: 上海
圈子: JBPM @net

       時間: 2007-06-01 16:53    評級:   11111 (0位會員評分)          

ellie4c 寫道
這樣的話 如果一個對象有多個操作指令的話 比如insert(a),update(a),delete(a)全部在一個事務里面的話,這樣同步起來代價就太大了,不知道其他看過代碼的人 有沒有什么想法

第一你要考慮到實際開發中有沒有這種問題,第二,save之后的update只不過是操作一級緩存,沒有同步的問題,delete也是如此,怎么會有同步的問題???
返回頂端  17樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 16:53  
我來評分:  請先 登錄
ellie4c
等級: 初級會員
ellie4c的博客:ellie4c

文章: 20
積分: 27
圈子: Tapestry

       時間: 2007-06-01 16:58    評級:   11111 (0位會員評分)          

這是算法里面應該考慮的一種情況,我們不要偏離主題,你上面的根據指令來判斷 應該會有這種情況,我想聽聽有沒有那位高手看懂過里面的算法實現?我一向覺得不能只會用。

返回頂端  18樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-01 16:58  
我來評分:  請先 登錄
huangyiiiiii
等級: 初級會員
huangyiiiiii的博客:codeplayer

性別:
文章: 84
積分: 80
圈子: Python

       時間: 2007-06-03 01:31    評級:   11111 (0位會員評分)          

hibernate 沒用過,不過根據我用另一個python下的類似hibernate的ORM的經驗,你們所謂的一級二級緩存應該是這樣的吧:

代碼
  1. session = create_session()  
  2. user = User(name='hello',...) # 這個是所謂的二級緩存?  
  3. session.save(user) # 這里還沒有實際操作數據庫 莫非就是你們所謂的更新了一級緩存?  
  4. session.flush() # 這里修改了數據庫了  

不過在我看來這里并沒有兩級緩存,user.save() 時只是讓 ORM 記錄下來有一個 user 需要 save 了。包括屬性的修改也是如此,當修改一個屬性的值時,ORM 會先記下這個需要更新的對象。
也就是說在 user.save() 后,session.flush() 前查詢 user 表,應該是得不到剛創建的這個 user 對象的。
ORM 在最后 session.flush() 時要干比較多的事情,根據所記錄下的對象的保存修改刪除等變化,并通過分析各個表之間的外鍵關聯等,得出一個合適的 SQL 實際執行的順序,這里用到的算法叫做 topological sort。
另外 SQLAlchemy 里還有個像是緩存的東西:Identity Map(簡單搜了一下,這個概念應該是來自 Hibernate 的),莫非這就是你們所說的一級緩存?不過我覺得這東西就作用來看應該不能算是緩存,只是用來保持數據一致性的。
返回頂端  19樓
瀏覽發表者的主頁 閱讀會員資料 發送站內短信   最后更新:2007-06-03 01:31  
我來評分:  請先 登錄
ellie4c
等級: 初級會員
ellie4c的博客:ellie4c

文章: 20
積分: 27
圈子: Tapestry

       時間: 2007-06-03 10:26    評級:   11111 (0位會員評分)          

我最近在看它的源碼,沒什么用,不過我覺得這樣的算法大家覺得行不行,就是orm框架 每次都記錄一級緩存里面對象的最后的操作狀態,不管它前面執行過么操作,在最后提交以后遍歷整個一級緩存的map同步。
如果事
insert:新增到二級緩存
update:新增或更新到二級緩存
delete:查找二級緩存找到就刪除
select:不做操作,
但是select操作會發生一種例外就是先insert/update再select所以
select操作只是從二級緩存到一級緩存或者DB到一級的時候記錄select操作,如果這個對象再一級緩存里面已經存在,就算他再次被查找到也不去更新他的select操作。這樣的算法大家看看有沒有什么問題,還有其他的好點的算法嗎?



session的一級緩存中的對象只有該session自己能取到,其他session是取不到的,所以不存在事務問題,實際所有操作都在一個事務中。

而sessionFactory的二級緩存是所有session共用的,所以要考慮事務問題,在一個session對數據進行操作時,需要保證對于 其他session不管是查詢數據庫還是查詢二級緩存取得的數據必須是一致的,即如果二級緩存中有緩存的數據,那么該數據和數據庫中的數據是一致的。

因此如果一個session中對數據進行了修改,那么只有在它把事務提交后才會把數據更新到二級緩存中(如果是讀寫的)。
具體來說,如果在一個session中修改了一條數據,在它還沒有寫到數據庫時,此時數據庫和二級緩存中的數據仍然是一致的,它不會去改變二級緩 存中的數據;在數據flush刷出,寫到數據庫中后,但還沒有提交,此時如果有其他session要從數據庫中讀取該數據的話應該是等待該修改事務的提 交,因此該修改數據的session會將二級緩存中的該id對應的數據對象失效掉(或者說鎖定),不讓其他session從二級緩存中取該數據,以保持和 數據庫的一致性;當session將事務提交后會將修改后的數據更新到二級緩存中。

對于沒有修改的從數據庫中讀到的數據都會更新到二級緩存中(當然必須設定了該對象類使用二級緩存)。