Spring BatchのJobRepositoryのSERIALIZED分離レベルでこの例外が発生しています:
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
;ネストされた例外はJava.sql.SQLException:ORA-08177:このトランザクションのアクセスをシリアル化できません
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)
1つのジョブのみを実行する場合、他に何も並行して実行されません。 JobRepositoryの分離レベルをISOLATION_READ_COMMITTEDに変更すると、例外はなくなりました。
この例外の理由は何ですか?
そのメソッドのデフォルトの分離レベルはSERIALIZABLEです。これは非常に積極的です。READ_COMMITTEDも同様に機能します。 2つのプロセスがこの方法で衝突する可能性が低い場合、READ_UNCOMMITTEDは問題ありません。ただし、create *メソッドの呼び出しは非常に短いため、データベースプラットフォームがサポートしている限り、SERIALIZEDが問題を引き起こす可能性は低いです 。
私は同じ問題を抱えていました、そして実際にはjobRepositoryレベルでの分離が重要です。ここに私のために働くコードの例を示します:
<batch:job-repository id="jobRepository"
data-source="dataSource" transaction-manager="transactionManager"
isolation-level-for-create="READ_COMMITTED" table-prefix="SB_" />
シリアル化されたトランザクションを使用する場合は、 Oracle Docs ごとにテーブルのinitransパラメーターを増やす必要があります。シリアル化されたトランザクションを処理するには、3以上にする必要があります。
alter table BATCH_.... INITRANS 3
INI_TRANSを100にジャッキアップしようとしましたが、まだ問題が発生していました
ROWDEPENDENCIESをテーブルの作成に追加することを提案するこの記事を見つけました。
http://www.devx.com/dbzone/Article/41591?pf=true
INI_TRANSと現在のROWDEPENDENCIESを使用する私にとって、Serializedの例外はなくなりました。
更新:完全なソリューションではないことが判明しました。このシリアル化された例外のイベントが一晩で発生しました。単一の障害が発生する前に何百回も実行されたので、これははるかに優れていますが、ROWDEPENDENCIESを使用することはまだ完全なソリューションではないようです。
この問題の回避策があります。
以下の手順に従ってください。
BATCH_JOB_INSTANCE
、BATCH_JOB_EXECUTION
、およびBATCH_JOB_EXECUTION_PARAMS
テーブルにいくつかのダミーレコードを挿入します。 (コミットすることを忘れないでください)以下のようにisolationLevelForCreateを追加することで、このエラーを解決できました。
<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>