Spring Batch ORA-08177: 단일 작업을 실행할 때 이 트랜잭션에 대한 액세스를 직렬화할 수 없습니다, 직렬화된 분리 수준
Spring Batch의 Job Repository에서 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입니다.SQL 예외: 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)
하나의 작업만 실행하고 다른 작업은 병렬로 실행하지 않습니다.JobRepository에 대한 분리 수준을 ISOLISION_READ_COMMITmitted로 변경하면 예외가 사라집니다.
이 예외의 이유는 무엇입니까?
이 메서드에 대한 기본 분리 수준은 SERIALIZE(직렬)이며, 이는 매우 공격적입니다. READ_COMMITTED도 마찬가지로 작동합니다. READ_UNCOMMITTED는 두 프로세스가 이러한 방식으로 충돌하지 않을 가능성이 있는 경우 괜찮습니다.그러나 create* 메서드에 대한 호출은 매우 짧기 때문에 데이터베이스 플랫폼이 이 메서드를 지원하는 한 SERIALIZED가 문제를 일으킬 가능성은 거의 없습니다.
저도 같은 문제를 겪었고, 저장소 수준에서 효과적으로 격리하는 것이 핵심입니다. 다음은 제게 맞는 코드의 예입니다.
<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
Spring Batch 애플리케이션(Spring Boot 2.3.3)에서도 동일한 문제가 발생했습니다.솔루션은 다음과 같습니다.
제거한다.
@EnableTransactionManagement
a부터@Configuration
데이터 소스가 구성된 클래스입니다.(@Transactional
또한 제거해야 합니다.)application.yaml에 다음을 추가합니다.
배치:리포지토리:생성에 대한 분리 수준:ISOLATION_READ_COMMITED
INI_TRANS를 100으로 끌어올리려고 시도했지만 여전히 문제가 발생했습니다.
테이블 작성에 행 종속성을 추가할 것을 제안하는 이 기사를 찾았습니다.
http://www.devx.com/dbzone/Article/41591?pf=true
INI_TRANS 및 현재 ROW Dependencies를 사용하는 저의 경우 Serialized에 대한 예외가 사라졌습니다.
업데이트: 완벽한 솔루션은 아닌 것으로 밝혀졌습니다.우리는 하룻밤 사이에 이런 일련의 예외적인 사건이 하나 있었습니다.단일 장애가 발생하기 전에 수백 번의 실행을 수행했기 때문에 훨씬 나아졌지만 ROWDEPINCES를 사용하는 것이 아직 완벽한 솔루션은 아닌 것 같습니다.
이 문제에 대한 해결책이 있습니다.
아래 단계를 따릅니다.
- 데이터베이스에 테이블을 수동으로 작성합니다(링크).
- 를 몇개의 레코를 삽합니다에 삽입합니다.
BATCH_JOB_INSTANCE
,BATCH_JOB_EXECUTION
그리고.BATCH_JOB_EXECUTION_PARAMS
테이블. (약속하는 것을 잊지 마세요) - 오류가 해결되었습니다.즐거운 시간 되세요.
분리를 추가하여 이 오류를 해결할 수 있었습니다.아래와 같은 생성 수준:
<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>
Oracle 트랜잭션 격리 수준 "SERIALIABLEIBLE"과 함께 테이블 생성 문에 "PRIMARY KEY" 한정자가 사용된 문제를 추적할 수 있었습니다.다음과 같은 간단한 SQL 스크립트를 사용하여 이를 테스트할 수 있습니다.
CREATE TABLE test1 (
test_id NUMBER(1) NOT NULL PRIMARY KEY
);
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
INSERT INTO test1 VALUES ( 1 );
COMMIT;
결과: ORA-08177 오류.
근본 원인:
이 문제는 Spring Batch 코드와 관련된 것이 아니라 Oracle이 버전 11.2 이후에 테이블을 생성하는 방식과 관련이 있습니다. 자세한 내용은 여기를 참조하십시오. https://oracle-base.com/articles/11g/segment-creation-on-demand-11gr2)
일반적인 문제에 대한 자세한 설명은 https://asktom.oracle.com/pls/apex/asktom.search?tag=isolation-level-serialization 에서 확인할 수 있습니다.
사용한 솔루션:
위의 create 절에 "SEGENCE CREATION Immediate"를 추가하면 문제가 해결되었습니다.
CREATE TABLE test1 (
test_id NUMBER(1) NOT NULL PRIMARY KEY
)
SEGMENT CREATION IMMEDIATE;
이에 따라 Spring Batch 작업 저장소에 대한 모든 "CREATE TABLE" 문에 동일한 내용을 추가했으며 작업이 잘 진행되었습니다.
database.maximumPoolSize 크기를 3에서 5로 늘리면 오류가 해결되었습니다.
저의 경우 DB 쪽에서 문제가 발생했을 때 재실행 시에도 동일한 문제가 발생합니다.
해결하기 위해 아래 테이블을 모두 정리하고 그 이후에 다시 실행해도 괜찮을 것 같습니다.
- BATCH_JOB_EXECUTION
- BATCH_JOB_EXECUTION_CONTACLE
- BATCH_JOB_EXECUTION_PARAMS
- BATCH_JOB_INSTANCE
- 배치_스텝_실행
- BATCH_STEP_EXECUTION_CONTACLE
언급URL : https://stackoverflow.com/questions/22364432/spring-batch-ora-08177-cant-serialize-access-for-this-transaction-when-running
'programing' 카테고리의 다른 글
스트링 배열을 numpy로 플로트 배열로 변환하는 방법은 무엇입니까? (0) | 2023.06.08 |
---|---|
번들에 node_modules 종속성이 있는 프로덕션용 NestJS 앱을 올바르게 구축하는 방법은 무엇입니까? (0) | 2023.06.08 |
MariaDB 10.1.44 row_number()가 없는 행 번호 (0) | 2023.06.08 |
팬더 병합 - 열 중복 방지 방법 (0) | 2023.06.08 |
Excel VBA 런타임 오류 '424' 개체가 필요합니다. (0) | 2023.06.08 |