2011-02-23 80 views
4

我有可能產生併發插入和更新(經由Session.saveOrUpdate)一個Hibernate應用到記錄與相同主鍵,這是分配。這些交易有點長時間運行,平均可能需要15秒(因爲數據是從遠程來源收集的,並在進入時保持不變)。我的數據庫隔離級別設置爲讀取已提交,並使用MySQL和InnoDB。死鎖處理在長時間運行的Hibernate事務

問題是這種情況下創建過多的鎖等待該超時,無論是作爲死鎖或長事務的結果。這導致我有幾個問題:

  • 數據庫引擎是否只在事務提交時釋放其鎖?
  • 如果是這樣的話,我應該尋求縮短我的交易嗎?
  • 如果是這樣,那麼使用單獨的讀寫事務是一個好習慣,寫事務可以做得很短,並且只有在收集到所有數據後纔會發生(我的事務長度的大部分包括收集遠程數據)。

編輯:

這裏有一個簡單的測試近似於什麼,我相信正在發生的事情。由於我正在處理長時間運行的事務,因此在第一次刷新後很久就會發生提交。所以,只是想說明我的情況,我離開提交了測試:

@Entity 
static class Person { 
    @Id 
    Long id = Long.valueOf(1); 
    @Version 
    private int version; 
} 

@Test 
public void updateTest() { 
    for (int i = 0; i < 5; i++) { 
     new Thread() { 
      public void run() { 
       Session s = sf.openSession(); 
       Transaction t = s.beginTransaction(); 
       Person p = new Person(); 
       s.saveOrUpdate(p); 
       s.flush(); // Waits... 
      } 
     }.run(); 
    } 
} 

而查詢這個期待的產生,在等待第二個插入:

select id, version from person where id=? 
insert into person (version, id) values (?, ?) 
select id, version from person where id=? 
insert into person (version, id) values (?, ?) 
+0

我討厭遇到這些類型的問題,我5年以後遇到完全相同的問題,我看沒有答案:( – 2016-03-13 18:06:56

回答

1

這是正確的,只是數據庫版本鎖當交易被提交時。由於您使用的是休眠,所以您可以使用樂觀鎖定,這會鎖定數據庫很長一段時間。從本質上講,hibernate可以完成你的建議,將讀寫部分分離成單獨的事務。在寫入時,它會檢查數據庫中內存中的數據沒有同時發生更改。

+0

從我的理解,使樂觀鎖定Hibernate的簡單涉及在我的實體中的一個int上拋出一個@Version註釋,我嘗試過使用上面描述的場景,但沒有任何好處,請參閱我添加到使用樂觀版本控制重現場景的原始文章中的測試。 – Josh 2011-02-23 22:57:36