0

我已经建立了一个休息服务来插入大行。要插入大量行,我正在批量使用插入。什么可能导致这个 restful 服务片段中的死锁。

    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();

但我收到此错误:

 
说明:org.springframework.dao.ConcurrencyFailureException: SqlMapClient 操作;SQL [];   
--- 应用参数映射时发生错误。   
--- 检查 insertData-InlineParameterMap。   
--- 检查语句(更新失败)。   
--- 原因:java.sql.SQLException:事务(进程 ID 3121)与另一个进程在锁资源上死锁,并被选为死锁牺牲品。重新运行事务。; 嵌套异常是 com.ibatis.common.jdbc.exception.NestedSQLException:

4

1 回答 1

0

死锁表示程序设计问题。数据库创建在数据被修改时锁定数据的事务。如果您修改数据“A”,然后修改数据“B”,数据库将锁定这两个数据点。根据您的数据库和设置,“A”和“B”的实际锁定可能是单个记录、记录组(页),甚至是整个表。

如果您的事务已经修改了“A”,并且现在正在尝试修改“B”,但是其他一些程序已经修改了“B”,并且现在正在尝试修改“A”,那么您就有了死锁。

一些数据库(如 DB2)指示存在死锁,即使它可能只是锁超时(一个进程尝试了 60 秒以获得锁,但失败了)。DB2 有特殊的子代码来指示潜在的死锁原因是什么。

解决死锁的唯一方法是让数据库选择一个进程杀死,让另一个进程通过。您的进程已被杀死。

死锁问题表明程序设计问题。这是一个众所周知的问题,唯一可靠的解决方案是确保您的所有程序都以彼此相同的顺序锁定数据。这样你就不会遇到死锁。死锁的另一个常见原因是程序没有在逻辑中的适当位置提交工作。

编辑-在您的情况下,您声称要分批插入 500 个,但您的开始/提交位于所有内容的开头和结尾。您需要将 start/execute Batch 和 start/commit Transaction放在循环中。您正在锁定所有正在插入的记录

//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 并获得结果(希望这次没有死锁)。

于 2013-05-07T14:06:03.237 回答