2013-05-07 92 views
0

我已經構建了一個rest-ful服務來插入大型行。要插入大量的行,我使用批量插入。什麼可能導致這個寧靜服務片段中的僵局。ConcurrencyFailureException:在批量添加大量行時出現死鎖

final SqlMapClient sqlMapClient = getSqlMapClientTemplate().getSqlMapClient(); 
    sqlMapClient.startTransaction(); 
    sqlMapClient.startBatch(); 

    //data is of size say 10,000 i am dividing into 500 and inserting 
    do { 
     data500 = next 500 of data 
     getSqlMapClientTemplate().insert("insertData", data500); 
    }while(data500 is not empty) 

    sqlMapClient.executeBatch(); 
    sqlMapClient.commitTransaction(); 

但我收到此錯誤:

 
Description : org.springframework.dao.ConcurrencyFailureException: SqlMapClient operation; SQL []; 
--- The error occurred while applying a parameter map. 
--- Check the insertData-InlineParameterMap. 
--- Check the statement (update failed). 
--- Cause: java.sql.SQLException: Transaction (Process ID 3121) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException: 

回答

0

死鎖指示程序設計問題。數據庫創建事務,在數據被修改時鎖定數據。如果修改數據'A'然後修改數據'B',數據庫將同時鎖定這兩個數據點。根據您的數據庫和設置,'A'和'B'的實際鎖定可能是單個記錄,記錄組(頁面),甚至整個表格。

如果您的交易已經修改了'A',並且現在正在嘗試修改'B',但是其他一些程序已經修改了'B',並且現在正在嘗試修改'A',那麼您會遇到死鎖。

某些數據庫(如DB2)表明存在死鎖,即使它可能只是一個鎖定超時(某個進程嘗試了60秒來獲取鎖定,但失敗)。 DB2有特殊的子代碼來表明底層的死鎖原因是什麼。

死鎖的唯一解決方案是讓數據庫選擇其中一個進程來殺死另一個進程。你的過程已經死亡。

死鎖問題表示程序設計問題。這是一個衆所周知的問題,唯一可靠的解決方案是確保所有程序都以相同的順序鎖定數據。這樣你就不會遇到死鎖。死鎖的另一個常見原因是程序不能在邏輯中的適當位置提交工作。

編輯 - 在你的情況下,你聲稱你是以500批次插入它們,但你的開始/提交在的開頭和結尾都是。您需要將啓動/執行批處理和開始/提交交易循環內。你是抱着鎖插入

//data is of size say 10,000 i am dividing into 500 and inserting 
do { 
    sqlMapClient.startTransaction(); 
    sqlMapClient.startBatch(); 

    data500 = next 500 of data 
    getSqlMapClientTemplate().insert("insertData", data500); 

    sqlMapClient.executeBatch(); 
    sqlMapClient.commitTransaction(); 
}while(data500 is not empty) 

所有記錄或者,死鎖是「重試」的錯誤,如果你得到一個僵局,您可以重新運行SQL,讓你的結果(希望沒有死鎖這次)。

+0

編輯爲您的特定情況包括'修復'(您正在鎖定*所有10000左右*記錄(可能加上一個高位表鎖) – rolfl 2013-05-07 14:49:34

+0

但我想要輸入所有10000或不輸入。但在這種情況下,如果您在每批次之後提交,則可能只插入其中的一部分 – dumper 2013-05-08 06:56:02

+0

一個非常現實的可能性是,當您開始插入記錄時,會鎖定要插入的行/頁面,但是,在某個時間點,數據庫決定你有這麼多的鎖,它們不是單獨跟蹤它們的效率,而是將它們升級到一個單一的全表鎖,如果有其他進程正在修改,甚至可能從該表中選擇,那麼你有一個死鎖條件: – rolfl 2013-05-08 10:28:57