얼마전 배치를 추가하여 운영서버에 반영하였는데 위와 같은 에러가 뜨면서 쿼리들이 Lock에 걸리기 시작했다. Lock이 걸린 세션을 Kill 한 후 killed session의 connection을 정리 하려고 하였으나 lock에 걸려 서비스에 문제가 생겨 서버를 재기동하는 상황까지 발생하였다. 원인 분석이 명확하게 되지 않아 여러가지 방법을 시도하여 보았다.

 

  1. 배치주기 변경 : 기존 5초마다 반복실행하던 배치를 6분마다 작동으로 배치주기를 변경하였다.
  2. Lock이 걸린 쿼리를 사용하는 배치 인덱스 생성 및 쿼리 수정 : Lock 이 걸린 쿼리를 포함하고 있는 배치내에 모든 쿼리들을 전수조사하여 실행속도가 늦거나 인덱스를 타지 않고 Full Scan을 타는 쿼리들을 수정하였다.

위 두가지 개선책을 운영에 반영하여 봤지만 여전히 배치 처리량이 많은 새벽 3시에 쿼리가 Lock이 걸렸다. jboss JDBC 내의 pool size 가 작게 잡혀있어 해당 에러가 발생하였나 알아보았으나 아니였다.

 

이렇게 갈피를 잡지 못하던 와중 로직을 확인해보니 트랜잭션 처리가 되어있지 않은 것이 확인되었다. 배포대상을 조회 후 UPDATE 쿼리 실행 후 트랜잭션 반환이 제대로 이루어지지 않은 것이다.

 

해결책은 

  1. 필요한 곳에 트랜잭션을 선언하여 사용
  2. 함수 자체에 트랜잭션을 선언

 

// 필요한 곳에 트랜잭션을 생성하여 사용
public class A {

	@Autowired
    private DataSourceTransactionManager txManager;
    
    public void B {
    	TransactionStatus transactionStatus = CommonUtils.getTransactionStatus(txManager);
        
        // select - update 로직 
        
        txManager.commit(transactionStatus); // commit 처리
    }

}

 

 

// 함수 자체에 트랜잭션 처리
public class A {
    
    @Transactional
    public void B {
    	
    }

}

 

위와 같이 2가지 방법중 택1을 하여 문제를 해결할 수 있는 것으로 확인되었고, 이후 운영에 반영 후 결과는 지켜봐야 할 것 같다.

+ Recent posts