【问题标题】:JSR-352 with Liberty Profile - 'ORA-01002: fetch out of sequence'带有 Liberty 配置文件的 JSR-352 -“ORA-01002:无序获取”
【发布时间】:2017-02-16 04:21:56
【问题描述】:

我正在试验 Liberty Profile 中的 JSR-352 实现,在我的阅读器处理了我的 JDBC ResultSet 的前 10 项后,我被“ORA-01002: fetch out of sequence”错误所困扰。我的块大小设置为 100。

这是我的读者:

@Dependent
@Named("myItemReader")
public class MyItemReader extends AbstractItemReader {

    @Resource(name="jdbc/somedb",shareable=false)
    private DataSource lavDb;

    private PreparedStatement stmt;
    private ResultSet rs;

    @Override
    public void open(Serializable checkpoint) throws Exception {
        Connection con = lavDb.getConnection();
        con.setAutoCommit(false);
        stmt = con.prepareStatement("select id from sometable",
               ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
        rs = stmt.executeQuery();
    }

    @Override
    public MyInputRecord readItem() throws Exception{
        if(rs.next()){
            return new MyInputRecord(rs.getInt(1));
        }
        return null;
    }

    @Override
    public void close(){
        try{
            rs.close();
            stmt.close();
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
}

如果 ResultSet 处理发生在 open() 方法中,那么我不会遇到任何错误。

这是我的 server.xml 中的 batchPersistence 配置:

<dataSource id="oracle-wasadmin" jdbcDriverRef="wasoracledriver" jndiName="jdbc/wasoracledb" type="javax.sql.XADataSource">
    <properties.oracle URL="${wasadmin.jdbcurl}" password="xxxxxx" user="yyyyyy"/>
    <conionManager agedTimeout="1m" maxIdleTime="15m" maxPoolSize="25" minPoolSize="0"/>
</dataSource>

<jdbcDriver id="wasoracledriver" javax.sql.XADataSource="oracle.jdbc.xa.client.OracleXADataSource">
    <library>
        <fileset dir="${shared.resource.dir}/oracle" includes="*.jar"/>
    </library>
</jdbcDriver>

这是作业日志中的错误:

com.ibm.jbatch.container.exception.BatchContainerRuntimeException: Failure in Read-Process-Write Loop
    at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.invokeChunk(ChunkStepControllerImpl.java:702)
    at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.invokeCoreStep(ChunkStepControllerImpl.java:792)
    at com.ibm.jbatch.container.controller.impl.BaseStepControllerImpl.execute(BaseStepControllerImpl.java:292)
    at com.ibm.jbatch.container.controller.impl.ExecutionTransitioner.doExecutionLoop(ExecutionTransitioner.java:118)
    at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl.executeCoreTransitionLoop(WorkUnitThreadControllerImpl.java:94)
    at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl.executeWorkUnit(WorkUnitThreadControllerImpl.java:155)
    at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl$AbstractControllerHelper.runExecutionOnThread(WorkUnitThreadControllerImpl.java:480)
    at com.ibm.jbatch.container.controller.impl.WorkUnitThreadControllerImpl.runExecutionOnThread(WorkUnitThreadControllerImpl.java:90)
    at com.ibm.jbatch.container.util.BatchWorkUnit.run(BatchWorkUnit.java:117)
    at com.ibm.ws.context.service.serializable.ContextualRunnable.run(ContextualRunnable.java:80)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.ibm.jbatch.container.exception.BatchContainerRuntimeException: java.sql.SQLException: ORA-01002: fetch out of sequence

    at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.readItem(ChunkStepControllerImpl.java:354)
    at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.readAndProcess(ChunkStepControllerImpl.java:245)
    at com.ibm.jbatch.container.controller.impl.ChunkStepControllerImpl.invokeChunk(ChunkStepControllerImpl.java:626)
    ... 14 more
Caused by: java.sql.SQLException: ORA-01002: fetch out of sequence

如果有帮助,我还有其他日志等。提前致谢。

【问题讨论】:

  • 虽然与您的异常无关,但我假设您 server.xml 中的“conionManager”是一个错字?
  • 是的,这是帖子中的错字,server.xml 的值正确。
  • 您是否尝试将ResultSet.HOLD_CURSORS_OVER_COMMIT 标志添加到您的prepareStatement 中的其他标志?
  • 尝试将 prepareStatmemt 更改为 stmt = con.prepareStatement("select id from sometable", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); ORA-01002 仍然存在。如果我添加stmt.setFetchSize(100000);,那么我的工作就会完成。
  • 它适用于 10 个项目似乎很奇怪。我知道你说你的块大小是 100,但我想知道是否有任何方法可以最终得到 10 的块大小。您可以粘贴显示块步骤定义的 JSL (XML) sn-p 吗?

标签: websphere-liberty jsr352 java-batch


【解决方案1】:

不要跨线程缓存 JDBC Statement 或 ResultSet 实例。 JDBC 编程模型不支持多线程访问,这可能就是您遇到此错误的原因。以及为什么它在 open 方法中运行良好,该方法在单个线程上运行。使用 JDBC 时,可以缓存 DataSource,但不能缓存 Connection 或 Connection 下的任何内容。让应用程序服务器管理连接和语句的池,它以线程安全的方式进行。

【讨论】:

  • 这个想法是通过单个查询有效地滚动结果集,而不是在每个 readItem 调用上设置连接、语句和结果集。我也以这篇文章为指导:radcortez.com/…
  • 我忽略了批处理正在被使用,所以这些操作实际上是在同一个线程上运行的,但是如果 oracle 不允许在 xa 事务提交中保持游标打开,该建议仍然适用。
  • 不小心按下回车键。这是评论的其余部分。您发现的文章可能是针对单阶段数据源编写的,从 JDBC 驱动程序的角度来看,该数据源将是 connection.commit 而不是 xa commit,这可能允许您继续使用游标。我还应该指出,如果使用这种方法,请务必确保在 close 方法中关闭连接,以免泄漏。
猜你喜欢
  • 2013-04-19
  • 1970-01-01
  • 2013-09-07
  • 2016-07-11
  • 1970-01-01
  • 2023-03-04
  • 2016-06-09
相关资源
最近更新 更多