问题描述
我的一个批处理作业(处理起来真的很繁重)抛出异常和日志。
老实说,如果由内存问题引起的协议违反反之亦然,我在某些时候会迷失方向。
2021-05-08 13:55:52,190 ERROR TransactionAspectSupport - Application exception overridden by rollback exception
java.lang.OutOfMemoryError: Java heap space
at oracle.jdbc.driver.T4CBlobAccessor.checkAndAllocateLobPrefetchMemory(T4CBlobAccessor.java:319)
at oracle.jdbc.driver.T4CBlobAccessor.handlePrefetch(T4CBlobAccessor.java:504)
at oracle.jdbc.driver.T4CBlobAccessor.unmarshalOneRow(T4CBlobAccessor.java:191)
at oracle.jdbc.driver.T4CTTIrxd.unmarshal(T4CTTIrxd.java:934)
at oracle.jdbc.driver.T4CTTIrxd.unmarshal(T4CTTIrxd.java:853)
at oracle.jdbc.driver.T4C8Oall.readRXD(T4C8Oall.java:699)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:337)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:191)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:523)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1010)
at oracle.jdbc.driver.OracleStatement.executeMaybedescribe(OracleStatement.java:1185)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1275)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3576)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3620)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1491)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:76)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
at org.hibernate.loader.Loader.doQuery(Loader.java:802)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.doList(Loader.java:2542)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
at org.hibernate.loader.Loader.list(Loader.java:2271)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:119)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1716)
at org.hibernate.impl.Criteriaimpl.list(Criteriaimpl.java:347)
at com.***.property.dao.hibernate.CompanySystemPropertyHibernateDao.retrieveCompanySystemProperty(CompanySystemPropertyHibernateDao.java:107)
at sun.reflect.GeneratedMethodAccessor574.invoke(UnkNown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
2021-05-08 14:05:46,590 ERROR TaskUtils$LoggingErrorHandler - Unexpected error occurred in scheduled task.
org.springframework.transaction.TransactionSystemException: Could not roll back Hibernate transaction; nested exception is org.hibernate.TransactionException: JDBC rollback Failed
at org.springframework.orm.hibernate3.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:680)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:846)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:823)
at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:493)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:264)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy68.refresh(UnkNown Source)
at sun.reflect.GeneratedMethodAccessor571.invoke(UnkNown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
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: org.hibernate.TransactionException: JDBC rollback Failed
at org.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:200)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:677)
... 20 more
Caused by: java.sql.sqlException: Protocol violation
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:459)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:191)
at oracle.jdbc.driver.T4C7Ocommoncall.doOROLLBACK(T4C7Ocommoncall.java:68)
at oracle.jdbc.driver.T4CConnection.doRollback(T4CConnection.java:649)
at oracle.jdbc.driver.PhysicalConnection.rollback(PhysicalConnection.java:3893)
at com.mchange.v2.c3p0.impl.NewProxyConnection.rollback(NewProxyConnection.java:855)
at org.hibernate.transaction.JDBCTransaction.rollbackAndResetAutoCommit(JDBCTransaction.java:213)
at org.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:192)
... 21 more
解决方法
如果有多个 LOB 列和较大的提取大小,则可能在 LOB 预取期间发生这种情况。
使用 LOB 预取,出于性能原因,服务器将数据与 LOB 定位器一起发送。默认情况下,它发送非常 LOB 的前 4k 字节数据。默认情况下,驱动程序还预取行 10 x 10。因此,如果每行有 10 个 LOB,每次“行提取”往返将消耗 10104k,即 400k 字节。当然,这假设每个 LOB 都有超过 4k 字节的数据。
要调整驱动程序并避免此错误,您可以减少默认提取大小或减少 LOB 预取大小。
有一个 JDBC 属性 CONNECTION_PROPERTY_DEFAULT_LOB_PREFETCH_SIZE 来配置不同的 LOB 预取大小。您可以将其设置为“1000”(1k 字节)以减少 LOB 在驱动程序上消耗的内存量。