Spring Batch ORA-08177: can't serialize access for this transaction when running single job, SERIALIZED isolation level

故事扮演 提交于 2019-12-17 09:33:48

问题


I am getting this exception with SERIALIZED isolation level on JobRepository in Spring Batch:

org.springframework.dao.CannotSerializeTransactionException: PreparedStatementCallback; SQL [INSERT into DATAFEED_APP.BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?)]; ORA-08177: can't serialize access for this transaction

; nested exception is java.sql.SQLException: ORA-08177: can't serialize access for this transaction

at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:269)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:603)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:812)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:868)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:872)
at org.springframework.batch.core.repository.dao.JdbcJobInstanceDao.createJobInstance(JdbcJobInstanceDao.java:105)
at org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:135)
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 org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean$1.invoke(AbstractJobRepositoryFactoryBean.java:172)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy27.createJobExecution(Unknown Source)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:124)
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 org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:117)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy61.run(Unknown Source)

when runing only one job, nothing else in parallel. When I change isolation level for JobRepository to ISOLATION_READ_COMMITTED the exception is gone.

What is the reason of this exception?


回答1:


From official doc - 4.3.1

The default isolation level for that method is SERIALIZABLE, which is quite aggressive: READ_COMMITTED would work just as well; READ_UNCOMMITTED would be fine if two processes are not likely to collide in this way. However, since a call to the create* method is quite short, it is unlikely that the SERIALIZED will cause problems, as long as the database platform supports it.




回答2:


I had the same problem, and effectively isolation in jobRepository level is the key, here is an example of code that works for me:

<batch:job-repository id="jobRepository"
    data-source="dataSource" transaction-manager="transactionManager"
    isolation-level-for-create="READ_COMMITTED" table-prefix="SB_" />   



回答3:


When using serialized transactions you need to increase the initrans parameter on the table per the Oracle Docs. To handle serialized transactions this needs to be 3 or more.

alter table BATCH_.... INITRANS 3



回答4:


We have tried jacking up INI_TRANS to 100 and we were still running into issues

I found this article that suggests adding ROWDEPENDENCIES to the creation of tables.

http://www.devx.com/dbzone/Article/41591?pf=true

For me with INI_TRANS & now ROWDEPENDENCIES the exceptions for Serialized have gone away.

Update: Turns out not to be a perfect solution. We did have one event of this SERIALIZED exception happen over night. Now that's much better as we had 100s of runs before a single failure but it appears that using ROWDEPENDENCIES isn't a yet a complete solution.




回答5:


I have got a workaround for this issue.

Follow below step.

  1. Manually create table in your database (Link).
  2. insert some dummy records in BATCH_JOB_INSTANCE, BATCH_JOB_EXECUTION and BATCH_JOB_EXECUTION_PARAMS table. (don't forget to commit)
  3. Error solved. enjoy.



回答6:


I was able to resolve this error by adding isolationLevelForCreate like below:

<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
        <property name="databaseType" value="ORACLE"/>
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManager" />
        <property name="isolationLevelForCreate" value="ISOLATION_READ_UNCOMMITTED"/>
    </bean>



回答7:


Increasing the database.maximumPoolSize size from 3 to 5 solved the error.



来源:https://stackoverflow.com/questions/22364432/spring-batch-ora-08177-cant-serialize-access-for-this-transaction-when-running

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!