我们使用的是notifyix 12.10版本。我们正在从Java批处理中删除54个表中的多行记录。我们在多线程中使用可调用策略。 请参考以下代码: SampleImpl.java:
Callable<Integer> callable=null;
List<Callable<Integer>> taskList = null;
List<Future<Integer>> futureList = null;
for (Map.Entry<String, String> entry : datas.entrySet()){
callable = new Callable<Integer>(){
public Integer call() throws Exception {
return sampleDel.callSqlDelete();
}
};
taskList.add(callable);
}
SampleDaoImpl:
public void callSqlDelete(){
Statement stmt = null;
connection.setAutoCommit(false);
stmt = connection.createStatement();
stmt.execute("SET LOCK MODE TO WAIT");
stmt.addBatch("DELETE FROM TABLE1 WHERE col1 IN(select from tableAAA where id=101)");
stmt.addBatch("DELETE FROM TABLE2 WHERE col1 IN(select from tableAAA where id=101)"");
int delCnt[] = stmt.executeBatch();
connection.commit();
}
在我们的Java代码中,我们已经将锁定模式设置为等待无限的时间间隔,但仍然收到以下异常:
java.sql.BatchUpdateException: Could not do a physical-order read to fetch next row.
at com.informix.jdbc.IfxStatement.executeBatch(IfxStatement.java:1650)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at oracle.ucp.jdbc.proxy.StatementProxyFactory.invoke(StatementProxyFactory.java:272)
at com.sun.proxy.$Proxy1.executeBatch(Unknown Source)
at com.sample.samplereport.dao.impl.SampleDAOPurgeImpl.processDelByStmts(SampleDAOPurgeImpl.java:1305)
at com.sample.samplereport.util.SamplePlSqlDeleter.callSqlDelete(SamplePlSqlDeleter.java:58)
at com.sample.samplereport.dao.impl.SampleDAOPurgeImpl$1.call(SampleDAOPurgeImpl.java:298)
at com.sample.samplereport.dao.impl.SampleDAOPurgeImpl$1.call(SampleDAOPurgeImpl.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)
请为上述问题提供帮助?
答案 0 :(得分:1)
对于这种类型的错误,通常查看Informix引擎还提供的ISAM错误代码通常会很有帮助。这提供了有关操作失败原因的更多信息,在这种情况下,操作为何无法读取下一行。获取ISAM错误的一种方法是在客户端Java环境中设置环境变量APPENDISAM。可能还有其他方法可以实现这一目标。仅供参考,您可以在https://www.ibm.com/support/knowledgecenter/SSGU8G_12.1.0/com.ibm.jdbc_pg.doc/ids_jdbc_040.htm
的Informix JDBC驱动程序文档中找到更多信息。对于这个问题,我怀疑ISAM错误可能是143“检测到死锁”。当一个线程需要等待另一个线程持有的锁时,另一个线程又正在等待第一个线程已经持有的锁时,就会出现这种情况。由于已将锁定模式设置为不超时等待,因此结果将是线程永远等待,因此服务器将返回死锁错误。
为帮助避免该问题,您应该检查是否使用行级锁定优先于TABLE1和TABLE2的页级锁定。您可能还需要检查使用的隔离级别。如果使用重复读隔离或数据库为ANSI模式,则子查询中使用的select语句将在它考虑的每一行上放置一个锁,尽管如果在“ id”列上有索引,则应将这些锁最小化。
在应用程序代码级别,死锁通常通过回滚事务并重复进行来处理。