트랜잭션 커밋이 제대로 이루어지지 않는 문제 in 스케줄링 작업

dev-jjun·2023년 8월 17일
0

트러블 슈팅

목록 보기
5/8
post-thumbnail

ᑒ 오류

o.h.engine.jdbc.spi.SqlExceptionHelper   : Lock wait timeout exceeded; try restarting transaction
org.springframework.transaction.**IllegalTransactionStateException**: Transaction is already completed - do not call commit or rollback more than once per transaction
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:804) ~[spring-tx-5.3.29.jar:5.3.29]
	at sopt.org.umbba.api.service.scheduler.ScheduleService.lambda$schedulePushAlarm$1(ScheduleService.java:108) ~[main/:na]
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.3.29.jar:5.3.29]
	at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:95) ~[spring-context-5.3.29.jar:5.3.29]
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[na:na]
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
	at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]

✐ 문제 원인 및 해결 방안

SqlExceptionHelper

데이터베이스에서 트랜잭션을 수행하는 동안, 다른 트랜잭션으로부터 요청된 락이 해제되지 않아 발생한 문제 ⇒ 락 충돌 발생 !

IllegalTransactionStateException

  • 트랜잭션 상태가 부적절할 때 발생 in 스프링 트랜잭션의 예외 클래스
  • 트랜잭션이 이미 완료된 상태에서 2번 이상의 커밋 또는 롤백이 시도된 경우 → 하나의 트랜잭션 내에서는 한 번의 커밋 또는 롤백만이 호출되어야 한다.


ミ⛧ 결론

[분석 결과] 트랜잭션 처리가 중복 호출되고 있다. 수동으로 관리해줘야 하는 부분과 자동으로 관리되는 부분의 경계를 찾아 제대로 트랜잭션 처리가 이루어지도록 해야 하고, 이를 위해서 로직과 경계를 수정해주자!

💡 적절한 트랜잭션 범위는?

좁게 가져가는 것이 좋다!

  • 데이터 일관성 유지 한 번에 처리되는 작업이 적으면 데이터 변경 사항을 추적하고 관리하기 쉬우므로, 데이터의 일관성을 더 쉽게 유지할 수 있음
  • 동시성 제어 여러 사용자 또는 프로세스가 동시에 작업을 수행할 때 트랜잭션 간 충돌을 덜 발생시킬 수 있음
  • 데이터베이스 락 최소화 적은 범위의 트랜잭션은 락을 더 적게 사용하므로 다른 작업에 대한 차단 가능성이 줄어듦

넓게 가져가는 것이 좋다!

  • 복잡한 비즈니스 로직 하나의 트랜잭션 범위 내여야만 비즈니스 로직이 완전히 처리되는 경우
  • 성능 고려 트랜잭션 시작~커밋 자체가 성능에 영향을 미칠 수 있음
  • 거대한 데이터 조작 많은 양의 데이터를 한번에 처리해야 하는 경우, 트랜잭션 범위를 확장하여 DB 작업을 최소화 하는 편이 더 효율적임
profile
서버 개발자를 꿈꾸며 성장하는 쭌입니다 😽

0개의 댓글