Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

773
Vistas
Spring Batch Deadlock: no se pudo incrementar la identidad; la excepción anidada es com.microsoft.sqlserver.jdbc.SQLServerException

Estamos en el proceso de pasar a Azure SQL Server desde Oracle DB para nuestra aplicación Spring Batch.

Recibo el siguiente error al intentar ejecutar dos trabajos diferentes al mismo tiempo que actualiza tablas diferentes, pero usa las mismas tablas BATCH_ comunes

Causado por: org.springframework.dao.DataAccessResourceFailureException: no se pudo incrementar la identidad; La excepción anidada es com.microsoft.sqlserver.jdbc.SQLServerException: la transacción (ID de proceso 167) se interbloqueó en los recursos de bloqueo con otro proceso y se eligió como víctima del interbloqueo. Vuelva a ejecutar la transacción. en org.springframework.jdbc.support.incrementer.SqlServerMaxValueIncrementer.getNextKey(SqlServerMaxValueIncrementer.java:124) ~[bat-applybatch-jobs-2.2.12-SNAPSHOT.jar:?] en org.springframework.jdbc.support.incrementer. AbstractDataFieldMaxValueIncrementer.nextLongValue(AbstractDataFieldMaxValueIncrementer.java:125)

Configuración de mi repositorio de trabajos

 <job-repository id="jobRepository" isolation-level-for-create="READ_COMMITED" />

interbloqueo de la base de datos

 <deadlock> <victim-list> <victimProcess id="process2a41675a4e8" /> </victim-list> <process-list> <process id="process2a41675a4e8" taskpriority="0" logused="280" waitresource="RID: 6:9:24682488:29" waittime="4984" ownerId="696000712" transactionname="implicit_transaction" lasttranstarted="2021-12-29T12:18:30.153" XDES="0x29a22bc4428" lockMode="U" schedulerid="4" kpid="52760" status="suspended" spid="173" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2021-12-29T12:18:30.157" lastbatchcompleted="2021-12-29T12:18:30.153" lastattention="1900-01-01T00:00:00.153" clientapp="Microsoft JDBC Driver for SQL Server" hostname="ServerName" hostpid="0" loginname="LoginName" isolationlevel="read committed (2)" xactid="696000712" currentdb="6" currentdbname="Database" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058"> <executionStack> <frame procname="unknown" queryhash="0xadc42a7474869694" queryplanhash="0x238c4f9df8a5d6cc" line="1" stmtstart="26" stmtend="146" sqlhandle="0x020000007654041849f4ffe980c136b592ccbe8260983e220000000000000000000000000000000000000000"> unknown </frame> <frame procname="unknown" queryhash="0xadc42a7474869694" queryplanhash="0x238c4f9df8a5d6cc" line="1" stmtend="126" sqlhandle="0x0200000045a2af306ade799ae9ffa65edc0f722c526e26330000000000000000000000000000000000000000"> unknown </frame> </executionStack> <inputbuf> delete from LoginName.BATCH_STEP_EXECUTION_SEQ where ID &lt; 10899 </inputbuf> </process> <process id="process2a42d680ca8" taskpriority="0" logused="420" waitresource="RID: 6:9:24682490:8" waittime="4984" ownerId="696000707" transactionname="implicit_transaction" lasttranstarted="2021-12-29T12:18:30.153" XDES="0x2a41ae18428" lockMode="U" schedulerid="7" kpid="53280" status="suspended" spid="129" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2021-12-29T12:18:30.153" lastbatchcompleted="2021-12-29T12:18:30.153" lastattention="1900-01-01T00:00:00.153" clientapp="Microsoft JDBC Driver for SQL Server" hostname="ServerName" hostpid="0" loginname="LoginName" isolationlevel="read committed (2)" xactid="696000707" currentdb="6" currentdbname="Database" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058"> <executionStack> <frame procname="unknown" queryhash="0xadc42a7474869694" queryplanhash="0x238c4f9df8a5d6cc" line="1" stmtstart="26" stmtend="146" sqlhandle="0x020000007654041849f4ffe980c136b592ccbe8260983e220000000000000000000000000000000000000000"> unknown </frame> <frame procname="unknown" queryhash="0xadc42a7474869694" queryplanhash="0x238c4f9df8a5d6cc" line="1" stmtend="126" sqlhandle="0x02000000a0f1f51de77e1eefa19367c42fc9d1938c2075020000000000000000000000000000000000000000"> unknown </frame> </executionStack> <inputbuf> delete from LoginName.BATCH_STEP_EXECUTION_SEQ where ID &lt; 10898 </inputbuf> </process> </process-list> <resource-list> <ridlock fileid="9" pageid="24682488" dbid="6" objectname="162589bb-bc36-4834-8bdc-e58a2deca742.LoginName.BATCH_STEP_EXECUTION_SEQ" id="lock2a043bbcc00" mode="X" associatedObjectId="72057594071547904"> <owner-list> <owner id="process2a42d680ca8" mode="X" /> </owner-list> <waiter-list> <waiter id="process2a41675a4e8" mode="U" requestType="wait" /> </waiter-list> </ridlock> <ridlock fileid="9" pageid="24682490" dbid="6" objectname="162589bb-bc36-4834-8bdc-e58a2deca742.LoginName.BATCH_STEP_EXECUTION_SEQ" id="lock29f5f1b7f00" mode="X" associatedObjectId="72057594071547904"> <owner-list> <owner id="process2a41675a4e8" mode="X" /> </owner-list> <waiter-list> <waiter id="process2a42d680ca8" mode="U" requestType="wait" /> </waiter-list> </ridlock> </resource-list> </deadlock>

intentado:

 <job-repository id="jobRepository" isolation-level-for-create="READ_UNCOMMITED" /> <job-repository id="jobRepository" isolation-level-for-create="ISOLATION_REPEATABLE_READ" /> <job-repository id="jobRepository" isolation-level-for-create="SERIALIZABLE" />

He creado las tablas como se destaca a continuación.

 CREATE TABLE BATCH_STEP_EXECUTION_SEQ ( ID BIGINT IDENTITY(<last Oracle sequence value>, 1) ); CREATE TABLE BATCH_JOB_EXECUTION_SEQ ( ID BIGINT IDENTITY(<last Oracle sequence value>, 1) ); CREATE TABLE BATCH_JOB_SEQ ( ID BIGINT IDENTITY(<last Oracle sequence value>, 1) );

¿cual es el problema? ¿Cómo puedo solucionar esto?

Actualización: definición de trabajo

 <bean id="simpleStep" class="org.springframework.batch.core.step.factory.SimpleStepFactoryBean" abstract="true"> <property name="transactionManager" ref="transactionManager" /> <property name="jobRepository" ref="jobRepository" /> <property name="startLimit" value="100" /> <property name="commitInterval" value="1" /> </bean>

Actualización # 2: ¿Puedo probar algo como esto?

 <bean id="informixIncrementer" class="com.bah.batch.informixsupport.InformixMaxValueIncrementerFactory"><property name="dataSource" ref="dataSource" /> <bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean" isolation-level-for-create="READ_COMMITTED" table-prefix="BATCH_"> <property name="incrementerFactory" ref="informixIncrementer"/> </bean>
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Me temo que este es un error conocido en Spring Batch 4.x que actualmente solo está planeado para resolverse con Spring Batch 5, que no se espera hasta dentro de un par de meses: https://github.com/spring- proyectos/lote de primavera/problemas/3927

Puede emular la corrección haciendo ajustes locales como en la confirmación de la corrección: https://github.com/spring-projects/spring-batch/commit/fe911c8456bb49a69b1c84c78c0a0e0fdf224803 , es decir

  • Ajustar el esquema para que contenga secuencias.
  • Cambie el DataFieldMaxValueIncrementerFactory que se usa para construir el JobRepository .

No creo que esto último sea factible con una configuración XML pura. La discusión sobre este tema contiene algunos consejos sobre cómo se puede hacer en Java: https://github.com/spring-projects/spring-batch/issues/1448

La personalización concreta depende de las personalizaciones que ya tenga, pero debería funcionar al menos aproximadamente de la siguiente manera. Puede aplicar la fábrica de incrementadores con un BatchConfigurer :

 @Bean public BatchConfigurer batchConfigurer(DataSource dataSource) { return new DefaultBatchConfigurer(dataSource) { @Override protected JobRepository createJobRepository() throws Exception { JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(getDataSource()); factory.setTransactionManager(getTransactionManager()); factory.setIncrementerFactory(new MyIncrementerFactory(getDataSource())); factory.afterPropertiesSet(); return factory.getObject(); } }; }

donde

 public class MyIncrementerFactory implements DataFieldMaxValueIncrementerFactory { private final DataSource dataSource; public MyIncrementerFactory(DataSource dataSource) { this.dataSource = dataSource; } @Override public DataFieldMaxValueIncrementer getIncrementer(String databaseType, String incrementerName) { return new SqlServerSequenceMaxValueIncrementer(dataSource, incrementerName); } @Override public boolean isSupportedIncrementerType(String databaseType) { return true; } @Override public String[] getSupportedIncrementerTypes() { return null; // method should not get called anyway } }

y SqlServerSequenceMaxValueIncrementer debe ser el incrementador de la confirmación.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda