Spring Batch ORA-08177: impossible de sérialiser l'accès pour cette transaction lors de l'exécution d'une seule tâche, niveau D'isolation sérialisé
j'obtiens cette exception avec le niveau D'isolation sérialisé sur JobRepository dans le Lot de printemps:
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
; l'exception imbriquée est java.SQL.SQLException: ORA-08177: ne peut pas sérialiser l'accès pour cette 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.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)
lorsqu'on exécute un seul travail, rien d'autre en parallèle. Quand je change le niveau d'isolation pour JobRepository en ISOLATION_READ_COMMITTED l'exception est partie.
Quelle est la raison de cette exception?
5 réponses
le niveau d'isolation par défaut pour cette méthode est sérialisable, ce qui est assez agressif: READ_COMMITTED fonctionnerait aussi bien; READ_UNCOMMITTED serait parfait si deux processus ne sont pas susceptibles de collision de cette façon. Toutefois, comme un appel à la créer* méthode est assez courte, il est peu probable que la sérialisation cause des problèmes, aussi longtemps que la plate-forme de base de données supporte .
j'ai eu le même problème, et effectivement l'isolement dans jobRepository niveau est la clé, voici un exemple de code qui fonctionne pour moi:
<batch:job-repository id="jobRepository"
data-source="dataSource" transaction-manager="transactionManager"
isolation-level-for-create="READ_COMMITTED" table-prefix="SB_" />
lorsque vous utilisez des transactions sérialisées, vous devez augmenter le paramètre initrans sur la table par le Oracle Docs. Pour traiter les transactions numérotées en série, cela doit être 3 ou plus.
alter table BATCH_.... INITRANS 3
nous avons essayé de brancher INI_TRANS à 100 et nous avions encore des problèmes
j'ai trouvé cet article qui suggère d'ajouter des dépendances de rang à la création de tables.
http://www.devx.com/dbzone/Article/41591?pf=true
pour moi avec INI_TRANS & maintenant ROWDEPENDENCIES les exceptions pour Serialized ont disparu.
mise à jour: il S'avère que ce n'est pas une solution parfaite. Nous avons eu un événement de cette exception sérialisée arriver au cours de la nuit. Maintenant, c'est beaucoup mieux car nous avions des centaines d'essais avant un seul échec, mais il semble que l'utilisation des dépendances de rang n'est pas encore une solution complète.
j'ai pu résoudre cette erreur en ajoutant isolationLevelForCreate comme suit:
<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>