【发布时间】:2020-11-27 19:54:02
【问题描述】:
我正在开发一个支持多个数据库的系统。所有的插入和更新都是批量发生的,同样是在 PreparedStatement 批处理的帮助下实现的。但是,对于 PostgreSQL,有很多时候它会导致批量更新死锁。我想知道是否有办法避免这种情况。
错误:检测到死锁
详情:进程 30655 等待数据库 17148 的关系 295507848 上的 ExclusiveLock;被进程 30662 阻止。
我有重试逻辑,但它给出了:
错误:当前事务被中止,命令被忽略,直到事务块结束
我对如何处理这种情况有点困惑。
public void InsertUpdateBatch(String auditPrefix, String _tableName, TableStructure<?> ts,
StringBuilder sb, String operation) throws Exception {
boolean retry = true;
boolean isInsert = "insert".equalsIgnoreCase(operation) ? true : false;
int minTry = 0;
int maxTries = 2;
ThreadLocal<PreparedStatement> statement = isInsert ? pstmt : updateStmt;
ThreadLocal<List<Object[]>> dataToProcess = isInsert ? insertBatchData : updateBatchData;
while (retry) {
try {
long t1 = System.currentTimeMillis();
int[] retCount = {};
retCount = statement.get().executeBatch();
// Clearing the batch and batch data
statement.get().clearBatch();
dataToProcess.get().clear();
if(isInsert) {
syncReport.addInsert(ts.getTableName(), retCount.length);
} else {
syncReport.addUpdate(ts.getTableName(), retCount.length);
}
this.syncReport.addDatabaseTime(t1, System.currentTimeMillis());
retry = false;
} catch (Exception e) {
// Clearing the batch explicitly
statement.get().clearBatch();
log.log(Level.INFO, "Thread " + Thread.currentThread().getName() + ": tried the operation " + operation + " for " + (minTry + 1) + " time(s)");
if (++minTry == maxTries) {
retry = false;
minTry = 0;
e.printStackTrace();
commitSynchException(auditPrefix, _tableName, ts, sb, operation, isInsert, e);
} else {
trackRecordCount(e, ts, !isInsert);
// Rebuild Batch
rebuildBatch(ts, dataToProcess.get(), e);
// Clearing old batch data after rebuilding the batch
dataToProcess.get().clear();
}
}
}
}
【问题讨论】:
标签: java postgresql prepared-statement database-deadlocks