Java多线程:Informix 12.10-无法执行物理顺序读取以获取下一行

Java多线程:Informix 12.10-无法执行物理顺序读取以获取下一行,java,multithreading,informix,Java,Multithreading,Informix,我们正在使用informix 12.10版本。我们正在从Java批处理中删除54个表中的多行记录。我们在多线程中使用可调用策略。 请参阅以下代码: SampleImpl.java: Callable<Integer> callable=null; List<Callable<Integer>> taskList = null; List<Future<Integer>> futureList = null; for (Map.Entry

我们正在使用informix 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);
}
在我们的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)

请就上述问题提供帮助?

对于此类错误,查看Informix引擎还提供的ISAM错误代码通常会有所帮助。这提供了有关操作失败原因的更多信息,在本例中是无法读取下一行的原因。获取ISAM错误的一种方法是在客户机Java环境中设置环境变量APPENDISAM。很可能还有其他方法来实现这一点。仅供参考,您可以在以下位置的Informix JDBC驱动程序文档中找到更多信息:

对于这个问题,我怀疑ISAM错误可能是143“deadlock detected”。这会导致一个线程需要等待另一个线程持有的锁,而另一个线程又在等待第一个线程已经持有的锁。由于已将锁定模式设置为无超时等待,因此结果将是线程永远等待,因此服务器将返回死锁错误

为了帮助避免该问题,您应该检查表1和表2是否优先使用行级锁定而不是页面级锁定。您可能还需要检查所使用的隔离级别。如果使用可重复读取隔离或数据库为ANSI模式,则子查询中使用的select语句将在它考虑的每一行上放置一个锁,尽管如果“id”列上有索引,则应最小化这些行


在应用程序代码级别,通常通过回滚事务并重复它来处理死锁

来自服务器的ISAM错误通常作为嵌套的SQLException附加。调用getCause()应该会揭示一个潜在的问题,正如@simon riddle所指出的,当多个线程删除试图删除相同的行并且永远等待彼此的锁时,可能会检测到死锁。
    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)