Database

커넥션 풀과 DB에서 병목이 발생하는 이유

자몽포도 2023. 10. 3. 12:15

스프링 부트 환경에서 개발을 하게 되면 HikariCP 커넥션 풀 라이브러리가 디폴트로 박혀있다. 커넥션 풀이란 커넥션 객체를 담은 자료구조를 의미한다. 커넥션을 얻기 위해서는 TCP 통신 및 DB 내부 검증(인증, 사용자의 접근 권한) 등을 거쳐야 하는데 이러한 과정을 미리 처리해둘 수 있기 때문에 시간적인 측면에서 효율적이다.

 

커넥션 풀에는 DB와 통신하기 위한 객체가 존재한다고 보면 된다. 

HikariDataSource dataSource = new HikariDataSource();
dataSource.setMaximumPoolSize(150);

 

 

DB를 통해서 최대 커넥션 수를 확인할 수 있다. 그래서 애플리케이션 레벨에서 PoolSize를 무한정 늘리더라도 커넥션을 맺지 못한다.

 

 

다음은 현재 사용중인 커넥션 수를 확인하는 명령어다. MySQL 기준 show processlist 명령을 내리면 더 상세하게 볼 수 있다.

 

 

실제로 테스트 코드를 실행시켜보면 사용중인 커넥션 수가 증가하는 것을 볼 수 있다.

 

@Test
void dataSourceConnectionPool() throws SQLException, InterruptedException {
    HikariDataSource dataSource = new HikariDataSource();
    dataSource.setJdbcUrl(URL);
    dataSource.setUsername(USERNAME);
    dataSource.setPassword(PASSWORD);
    dataSource.setMaximumPoolSize(100);

    for (int i = 0; i < 200; i++) {
        Connection con1 = dataSource.getConnection();
    }
}

 

결과

 

여기서 커넥션 수가 100개 이상으로 증가하지 않는 이유는 애플리케이션 레벨에서 커넥션 풀을 100개로 제한했기 때문이다. 그래서 for 루프에서 101번째부터는 커넥션 풀에 커넥션이 있는지 조회하게 되고 없으니 대기하게 된다. 바로 여기가 병목 지점이 되는 것이다. 물론 이 경우에는 커넥션을 close 하지 않아서 병목이 발생한다.

 

어찌됐건 중요한 건 슬로우 쿼리, 비정상적인 반복 호출 등 DB에서 응답을 내리고 커넥션을 반납하는 것보다 커넥션 요청 및 작업을 수행하는 양이 지속적으로 많게 된다면 병목이 발생하게 된다.