2017-03-17 20 views
3

我想要我的java代碼的多個實例讀取相同的一組數據,並且我想鎖定第一個實例讀取的記錄(行級別)。這樣第二個實例不會讀取相同的數據。這裏是我的示例代碼不起作用。如果我同時讀兩次,我會得到相同的記錄。爲了測試目的,我創建了列表1和列表2,並一個接一個地讀取兩次,以模擬多個實例讀取相同的數據。選擇更新不工作使用jdbc模板(posgres)

query = "SELECT * from xyz LIMIT 10 FOR UPDATE of xyz" 

      List<XYZ> list1= new ArrayList<XYZ>(); 
    List<XYZ> list2= new ArrayList<XYZ>(); 

    DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 
    def.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE); 

    TransactionStatus s=datasourceconfig.platformTransactionManager.getTransaction(def); 

    try { 
     list1= datasourceconfig.queryForObjectList(query , paramMap ,XYZ.class); 

    } catch (Exception ex) { 
     log.error("", ex); 
    } 

    try { 
     list2= datasourceconfig.queryForObjectList(query,paramMap,XYZ.class); 
    } catch (Exception ex) { 
     log.error("", ex); 
    } 

    empDsCfg.platformTransactionManager.commit(s); 

當我得到結果時,兩個列表都有相同的記錄。請幫助。

+0

我不確定您是否瞭解FOR UPDATE鎖的用途。他們(通常)只是阻止**其他**交易來修改選定的行(但從不*隱藏*他們)。如果您讀取同一個事務中的行,則永遠不會發生這種阻塞。而且,它在'SERIALIZABLE'隔離中的工作方式有所不同。請仔細閱讀[關於事務隔離的文檔](https://www.postgresql.org/docs/current/static/transaction-iso.html)。我們只能重複一遍,那裏有什麼。 – pozs

回答

0

如果您對PostgreSQL的9.5或更高版本,可以使用

SELECT ... 
LIMIT 10 
FOR UPDATE SKIP LOCKED; 

這將選擇並鎖定到尚未按併發事務鎖定十行。

可與所有PostgreSQL版本一起使用的替代方法是使用諮詢鎖這樣的:

SELECT ... 
WHERE pg_try_advisory_xact_lock(id) 
LIMIT 10 
FOR UPDATE; 

這裏id是主鍵,並假定它是一個整數值(一種類型的可以隱含地轉換爲bigint)。

如果該號碼沒有專有advisory lock,則該函數返回TRUE,並將鎖作爲副作用抓取。

注意:鎖只能保持一個事務的持續時間,因此一定要在單個事務中執行鎖定和後續數據修改。

+0

跳過鎖定工作在9.5,但不得不添加開始和結束/承諾它的工作 – Ammar

+0

我認爲這是理解,但我已經添加了一個說明來說清楚。 –