首页 > 解决方案 > 将 Oracle 驱动程序更新到 12.2.0.1.0 后出现“java.sql.SQLRecoverableException:IO 错误:操作中断”

问题描述

我最近将我们的 Oracle JDB 驱动程序更新为 12.2.0.1.0。

更新后,我们只是从 Oracle 驱动程序中得到了一些我们还没有遇到过的错误,我还没有找到关于如何解决这个问题的讨论。

我们在公司开发的应用程序有一个调度程序,用于管理不同作业的执行。

这些作业可以打开与数据库的连接并对其执行一些 SQL 查询(然后当然会关闭连接)。

这些作业是并行执行的(使用分叉机制)。

当然,最多可以并行执行的作业。

如果当前没有执行作业,则等待执行。

可以使用队列管理可以执行的作业的顺序。

以下错误发生在以下情况:调度程序并行执行允许同时运行的最大作业数,并且有作业等待执行。

在将要启动等待作业的那一刻(这意味着正在运行的作业已完成并且可以启动新作业)发生以下错误:

Caused by: de.fact.first.process.data.ProcessDataException: 
java.sql.SQLRecoverableException: IO Error: Operation interrupted
at 
JobDataFactoryImplJDBC.getByJobId(JobDataFactoryImplJDBC.java:210)
... 19 more
Caused by: java.sql.SQLRecoverableException: IO Error: Operation interrupted
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:761)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:904)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1082)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3780)
at oracle.jdbc.driver.T4CPreparedStatement.executeInternal(T4CPreparedStatement.java:1343)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3822)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1165)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:83)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:83)
at de.fact.first.process.data.JobDataFactoryImplJDBC.getByJobId(JobDataFactoryImplJDBC.java:205)
... 19 more
Caused by: java.io.InterruptedIOException: Operation interrupted
at oracle.net.nt.TimeoutSocketChannel.handleInterrupt(TimeoutSocketChannel.java:311)
at oracle.net.nt.TimeoutSocketChannel.write(TimeoutSocketChannel.java:221)
at oracle.net.ns.NIOPacket.writeToSocketChannel(NIOPacket.java:211)
at oracle.net.ns.NIONSDataChannel.writeDataToSocketChannel(NIONSDataChannel.java:181)
at oracle.net.ns.NIONSDataChannel.writeDataToSocketChannel(NIONSDataChannel.java:132)
at oracle.jdbc.driver.T4CMAREngineNIO.prepareForReading(T4CMAREngineNIO.java:96)
at oracle.jdbc.driver.T4CMAREngineNIO.unmarshalUB1(T4CMAREngineNIO.java:534)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:485)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:252)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:612)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:226)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:59)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:747)
... 28 more

我的第一个想法是,可能应用程序超过了连接数,因此 Oracle 中断了连接。

这不是问题,因为我增加了进程(和会话)的数量以及另外的分布式锁定超时。

即使调整了这些选项,问题仍然存在。

等待作业没有保持打开的连接。

当然,我可以说该错误仅发生在新的 Oracle 驱动程序中,该问题在旧驱动程序 (12.1.0.1.0) 中无法重现。

标签: oracledriver

解决方案


我们通过将OJDBC 驱动程序的配置选项testOnBorrow设置为 true 来解决此问题。同样,如果您使用 Tomcat 作为服务器,您还需要为 Tomcat 配置设置相同的属性为 true:

<Context reloadable="true" >

  <Resource name="jdbc/..."
            auth="Container"
            type="org.apache.commons.dbcp2.PoolingDataSource"
            factory=""
            scope="Shareable"
            dataSource="oracle"
            minIdle="0"
            maxIdle="50"
            maxActive="500"
            minEvictableIdleTimeMillis="1800000"
            numTestsPerEvictionRun="3"
            validationQuery="SELECT COUNT(*) FROM LANGUAGES"
            testOnBorrow="true"
            testOnReturn="false"
            testWhileIdle="true"
            timeBetweenEvictionRunsMillis="300000"/>

推荐阅读