[HikraiCP] SQLTimeoutException 발생 시 자동 Commit

half·2023년 9월 25일
0

HikariCP 오픈소스를 이용 중 발생한 이슈

쿼리 수행 중 Timeout이 발생할 경우에 아래 에러가 발생했다.

java.sql.SQLTimeoutException: The query has timed out.
	at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:226) ~[mssql-jdbc-7.2.2.jre8.jar:?]
	at com.microsoft.sqlserver.jdbc.SQLServerStatement.execute(SQLServerStatement.java:744) ~[mssql-jdbc-7.2.2.jre8.jar:?]
	at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:95) ~[HikariCP-3.3.1.jar:?]
	at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) ~[HikariCP-3.3.1.jar:?]
	...

이 경우에는 DBTimeout으로 Exception만 발생하는 것이 아니라 현재 연결되어 있는 DBConnection을 close 하기 때문에 후에 트랜잭션 처리에 어려움을 겪게 된다.

dao1.insertData(DTO); --- first Insert
dao1.insertData2(DTO); --- second Insert

해당 코드처럼 한 개의 로직에서 두개의 DB처리(INSERT, UPDATE, DELETE)를 할 경우 1번 정상처리 --> 2번에서 SQLTimeoutException (DB Timeout) 이 발생하게 되면 개별트랜잭션 처리를 하지 않아도 1번 insert 한 데이터가 Rollback 되지 않고 자동 Commit 처리가 된다.

또 자동 Commit 처리가 된 후 별도의 트랜잭션을 처리 할 수 없도록 Connection을 끊어버리게 되는데 해당 문제를 해결하기 위해 Hikari Config 설정 클래스를 추가해야 한다.

1) SQLExceptionOverride 상속 클래스 추가

import java.sql.SQLException;
import java.sql.SQLTimeoutException;
import com.zaxxer.hikari.SQLExceptionOverride;

public class HikariPreventQueryTimeoutEviction implements SQLExceptionOverride {

		@java.lang.Override
		public Override adjudicate(SQLException e) {
			if(e instanceof SQLTimeoutException) {
				return Override.DO_NOT_EVICT;
			}
			return null;
		}
	}

Hikari의 SQLExceptionOverride 클래스를 상속받아 SQLTimeoutException이 발생할 경우에만 Connection을 끊어주지 않도록 설정을 변경해 준다.

2) DataSource Property 설정

생성한 클래스를 데이터소스 생성시에 적용 할 수 있도록 DataSourceConfiguration에 추가

2-1 :: application.yml

spring:
  datasoutce:
    hikari:
      exception-override-class-name: com.spring.web.config.HikariPreventQueryTimeoutEviction
      # 생성한 SQLExceptionOverride 상속 클래스 추가

2-2 :: application.properties

spring.datasource.hikari.exception-override-class-name=com.spring.web.config.HikariPreventQueryTimeoutEviction
# 생성한 SQLExceptionOverride 상속 클래스 추가

3-3 :: DataSourceConfig.java

@Bean(name="dataSource")
@ConfigurationProperties(prefix="spring.datasource.oracle")
public DataSource dataSource() {
		HikariDataSource dataSource = new HikariDataSource();
		dataSource.setExceptionOverrideClassName(HikariPreventQueryTimeoutEviction.class.getName());
		return dataSource;
}

많이 사용하는 yaml, properties, java 설정을 추가하는 방법들이다.

출처 - https://github.com/brettwooldridge/HikariCP/issues/1388

profile
아메리카노 수혈 받는 중

0개의 댓글