web-dev-qa-db-fra.com

Spring Batch ORA-08177: impossible de sérialiser l'accès à cette transaction lors de l'exécution d'un travail unique, niveau d'isolement SERIALIZED

Je reçois cette exception avec le niveau d'isolement SERIALIZED sur JobRepository dans 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

; L'exception imbriquée est Java.sql.SQLException: ORA-08177: impossible de 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$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)

lors de l'exécution d'un seul travail, rien d'autre en parallèle. Lorsque je modifie le niveau d'isolement pour JobRepository en ISOLATION_READ_COMMITTED, l'exception a disparu.

Quelle est la raison de cette exception? 

17
padis

De document officiel - 4.3.1

Le niveau d'isolation par défaut pour cette méthode est SERIALIZABLE, qui est assez agressif: READ_COMMITTED fonctionnerait aussi bien; READ_UNCOMMITTED serait acceptable si deux processus ne risquent pas de entrer en collision de cette façon. Cependant, puisque l'appel à la méthode create * est assez court, il est peu probable que SERIALIZED pose problème, tant que la plate-forme de base de données le supporte}.

8
Luca Basso Ricci

J'ai eu le même problème, et l'isolation au niveau de jobRepository 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_" />   
6

Lorsque vous utilisez des transactions sérialisées, vous devez augmenter le paramètre initrans sur la table conformément au Oracle Docs . Pour traiter les transactions sérialisées, il faut être 3 ou plus.

alter table BATCH_.... INITRANS 3
4
mpkorstanje

Nous avons essayé de faire passer INI_TRANS à 100 et nous rencontrions toujours des problèmes 

J'ai trouvé cet article qui suggère d'ajouter ROWDEPENDENCIES à la création de tables.

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

Pour moi avec INI_TRANS et maintenant ROWDEPENDENCIES, les exceptions pour Serialized ont disparu.

Mise à jour: s'avère ne pas être une solution parfaite. Nous avons eu un événement de cette exception SERIALIZED qui s'est passé pendant la nuit. C’est bien mieux, car nous avions des centaines de tests avant un seul échec, mais il semble que l’utilisation de ROWDEPENDENCIES n’est pas encore une solution complète.

3
grbonk

J'ai une solution de contournement pour ce problème.

Suivez l'étape ci-dessous.

  1. Créez manuellement une table dans votre base de données ( Link ).
  2. insérez des enregistrements fictifs dans les tables BATCH_JOB_INSTANCE, BATCH_JOB_EXECUTION et BATCH_JOB_EXECUTION_PARAMS. (n'oubliez pas de vous engager)
  3. Erreur résolue. prendre plaisir.
0
Raj Kumar Gupta

J'ai pu résoudre cette erreur en ajoutant isolationLevelForCreate comme ci-dessous:

<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>
0
Bajal