개발자

DBCP에서 Unclosed JDBC Connection 발생원인

2023년 03월 10일조회 196

안녕하세요. spring 에서 DB : mariaDB DBCP 의존성 : commons-dbcp:1.3.jar 이렇게 DBCP 설정 사용하고있습니다. mariaDB 연결 옵션으로 allowMultiQueries=true 커넥션풀 관련옵션으로 initalSize=10 maxActive=150 두개만 설정되어있구요. 문제는 *APM 에서 "Unclose JDBC Connection" 이슈 로그가 하루 몇만 건씩 찍히고 있어서 보니 쿼리 실행할때마다 전부다 unclose 라고 나오고 있는데 원인을 모르겠습니다. 뭐때문에 이럴까요? jboss서버의 로그를 봐도 에러없이 들어오는 요청을 잘 처리하고 있고 그 외 소스상에서 직접 xxx.getConnection() 형태로 사용하고 있는 부분들도 connection.close() 하고있는지 확인했습니다. 한켠으로는 커넥션풀을 사용하고있으니 당연히 커넥션을 닫지 않고 사용한 커넥션을 다시 풀로 반환될 뿐이니 Unclose 는 당연한것이 아닌가? 싶기도 합니다. 이에 조언 구해봅니다 🤔 로그내용을 첨부할수없어 대신 링크하겠습니다. https://stackoverflow.com/questions/75693648/unclosed-jdbc-connection-issue-in-spring-dbcp-environment *APM: application performance manager

이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.

답변 2

유재영님의 프로필 사진

자문자답하러 왔습니다! 사용하고있던 Apache commons-dbcp 1.4.jar 라이브러리에 메모리 누수 버그가 있었습니다. 라이브러리 코드내부에 getMetaData() 에서 close 하지 않부분이 있다합니다. 읽어보면 좋은 상세정보 링크남길게요! https://d2.naver.com/helloworld/5102792

커리어리 AI 봇님의 프로필 사진

"Unclosed JDBC Connection"이 발생하는 이유는 여러 가지일 수 있지만, 가장 일반적인 원인은 커넥션을 사용한 후에 제대로 반환하지 않는 경우입니다. 이 경우, 커넥션은 계속해서 DBCP에서 사용 중인 상태로 남게되며, 다른 요청에서 사용할 수 없게 됩니다. 이로 인해 커넥션 풀이 고갈되고, 결국 성능 문제가 발생할 수 있습니다. 원인을 찾기 위해 다음 사항을 확인해보세요: 모든 JDBC 커넥션 사용 후 ' close() '를 호출하여 반환했는지 확인해주세요. 이는 ' ResultSet ', ' Statement ', ' PreparedStatement ' 및 ' Connection ' 객체 모두에 대해 적용됩니다. 이 작업을 수행하지 않으면 커넥션 풀이 고갈될 수 있습니다. ' finally ' 블록 또는 try-with-resources 구문을 사용하여 자원을 반환하는지 확인하세요. 이렇게 하면 예외가 발생하더라도 자원이 제대로 반환됩니다. 예시#1 또는 try-with-resources를 사용한 경우#2 3. DBCP 버전을 업그레이드해보세요. commons-dbcp는 현재 1.4 버전까지 출시되었습니다. 버전 업그레이드를 통해 발생할 수 있는 문제를 해결할 수 있습니다. 4. APM 도구의 버그일 수도 있습니다. APM 도구의 설정을 검토하고, 필요한 경우 도구를 업데이트하거나 다른 도구로 전환해보세요. 위의 사항들을 확인한 후에도 문제가 해결되지 않으면, 코드나 설정의 다른 부분에 문제가 있는 것으로 판단하고 추가적인 디버깅이 필요할 것입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#1
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;

try {
    conn = dataSource.getConnection();
    pstmt = conn.prepareStatement("SELECT * FROM users");
    rs = pstmt.executeQuery();

    // 처리 로직
} catch (SQLException e) {
    // 예외 처리 로직
} finally {
    if (rs != null) {
        try { rs.close(); } catch (SQLException e) { /* ignored */ }
    }
    if (pstmt != null) {
        try { pstmt.close(); } catch (SQLException e) { /* ignored */ }
    }
    if (conn != null) {
        try { conn.close(); } catch (SQLException e) { /* ignored */ }
    }
}


#2
try (Connection conn = dataSource.getConnection();
     PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users");
     ResultSet rs = pstmt.executeQuery()) {

    // 처리 로직
} catch (SQLException e) {
    // 예외 처리 로직
}

커리어리 AI 봇의 답변을 평가해 주세요!

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

목록으로
키워드로 질문 모아보기

실무, 커리어 고민이 있다면

새로운 질문 올리기

지금 가입하면 모든 질문의 답변을 볼 수 있어요!