2013-10-02 141 views
0

我使用JPA 2.0的Hibernate實現在表格行中創建一個計數器。我正在使用InnoDB引擎的MySQL 5.5。我試圖鎖定計數器行,以便JVM之外的任何進程都不能查看該計數器,直到我的代碼增加它爲止。我的代碼如下所示:休眠JPA - PESSIMISTIC.WRITE不工作

//inside a Transaction.... 

    //key is an enum 
    final PropertyKey key = PropertyKey.DEPLOY_COUNTER; 
    final Query query = 
    entityManager.createQuery("FROM Property s where propertyKey = :key").setParameter("key", key); 
    query.setLockMode(LockModeType.PESSIMISTIC_WRITE); 
    LOG.debug("Blocking (maybe) while waiting to update deploy counter"); 
    final Property counterAsProperty = (Property) query.getSingleResult(); 

    try 
    { 
    Thread.sleep(15000); 
    //while sleeping I use MySQL cli to check value of property in database 
    } 
    catch (InterruptedException e) 
    { 
    e.printStackTrace(); 
    } 

    //in java, increment counter by one and then save in db 
    //... 

我使用Thread.sleep()來暫停事務中間的代碼。當線程處於睡眠狀態時,我使用MySQL CLI客戶端登錄數據庫並檢查屬性的值。這會看起來是這樣的:

[email protected] [user]> begin work; 
Query OK, 0 rows affected (0.00 sec) 

[email protected] [user]> select * from property where property_key = 'DEPLOY_COUNTER'; 
+----+---------+-----------+--------------------+----------------+ 
| id | version | encrypted | property_key  | property_value | 
+----+---------+-----------+--------------------+----------------+ 
| 10 |  0 |   0 | DEPLOY_COUNTER  | 66    | 
+----+---------+-----------+--------------------+----------------+ 

注意如何查詢立即返回(0.00秒)時,我預期它阻止,直到線程已經退出睡眠和交易完成。我對LockModeType.PESSIMISTIC_WRITE的理解是,它應該將檢索到的行放入獨佔鎖中,不可用於其他事務的讀取或寫入。

注意:當線程正在休眠時,此行的更新會阻塞。

如果我設置了PESSIMISTIC_WRITE鎖定模式,爲什麼另一個數據庫連接可以在另一個事務正在運行時查看數據?

回答

1

默認的InnoDB隔離級別是REPEATABLE READ,它允許沒有排它鎖的事務讀取(但不更新)鎖定的記錄。這允許其他事務在記錄上進行非髒讀。 SERIALIZABLE似乎阻止對鎖定記錄的任何讀取。在設置hibernate連接屬性時,您可以設置隔離級別爲hibernate.connection.isolation,但這會影響所有連接,而不是我願意支付的費用。該SO後表示方式做到這一點每個連接,但是這種方法需要過時的方法:JPA and MySQL transaction isolation level

我結束了使用此處引用的

UPDATE counter SET value = LAST_INSERT_ID(value + 1); 
SELECT LAST_INSERT_ID(); 

方法之一:http://tedyoung.me/2011/04/14/jpa-counters-and-sequences/,它不需要任何鎖定。