transacciones serializacion distribuidas datos control concurrencia oracle spring-batch isolation-level

oracle - serializacion - control de concurrencia base de datos distribuidas



Spring Batch ORA-08177: no se puede serializar el acceso para esta transacción cuando se ejecuta un solo trabajo, nivel de aislamiento SERIALIZADO (6)

Cuando utilice transacciones serializadas, debe aumentar el parámetro initrans en la tabla según los documentos de Oracle . Para manejar transacciones serializadas esto debe ser 3 o más.

alter table BATCH_.... INITRANS 3

Recibo esta excepción con el nivel de aislamiento SERIALIZED en JobRepository en 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

; la excepción anidada es java.sql.SQLException: ORA-08177: no se puede serializar el acceso para esta transacción

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)

cuando se ejecuta un solo trabajo, nada más en paralelo. Cuando cambio el nivel de aislamiento para JobRepository a ISOLATION_READ_COMMITTED, la excepción desaparece.

¿Cuál es la razón de esta excepción?


Del documento oficial - 4.3.1.

El nivel de aislamiento predeterminado para ese método es SERIALIZABLE, que es bastante agresivo: READ_COMMITTED funcionaría igual de bien; READ_UNCOMMITTED estaría bien si no es probable que dos procesos colisionen de esta manera. Sin embargo, dado que una llamada al método create * es bastante corta, es poco probable que SERIALIZED cause problemas, siempre que la plataforma de la base de datos lo admita .


Hemos intentado elevar INI_TRANS a 100 y seguíamos teniendo problemas.

Encontré este artículo que sugiere agregar ROWDEPENDENCIES a la creación de tablas.

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

Para mí, con INI_TRANS y ahora ROWDEPENDENCIES, las excepciones para Serialized han desaparecido.

Actualización: Resulta que no es una solución perfecta. Tuvimos un evento de esta excepción SERIALIZADA que sucedió durante la noche. Ahora está mucho mejor, ya que tuvimos cientos de ejecuciones antes de un solo fallo, pero parece que el uso de ROWDEPENDENCIES no es una solución completa.


Pude resolver este error agregando isolationLevelForCreate como a continuación:

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


Tengo una solución para este problema.

Siga el siguiente paso.

  1. Crear manualmente la tabla en su base de datos ( Link ).
  2. inserte algunos registros ficticios en la BATCH_JOB_INSTANCE , BATCH_JOB_EXECUTION y BATCH_JOB_EXECUTION_PARAMS . (no olvides cometer)
  3. Error solucionado. disfrutar.

Tuve el mismo problema, y ​​efectivamente el aislamiento en el nivel JobRepository es la clave, aquí hay un ejemplo de código que me funciona:

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