1. DB Connection Pool이란?
- DB Connection이란?
- DB를 사용하기 위해 DB와 애플리케이션 간 통신을 할 수 있는 수단
- DB Connection은 Database Driver와 Database 연결 정보를 담은 URL이 필요함
- Java의 DB Connection은 JDBC를 주로 이용하는데, URL 타입을 사용함
- Driver type별로 지정하는 URL 예
Driver | URL | 설명 |
oracle.jdbc.driver.OracleDriver | jdbc:oracle:thin:@ipaddress:1521:ORA7 | oracle-DB/thin-Driver |
oracle.jdbc.driver.OracleDriver | jdbc:oracle:oci7:@ipaddress:1521:ORA7 | oracle-DB/OCI-Driver |
com.mysql.jdbc.Driver | jdbc:mysql://ip_address:3306/database_name | mysql |
sun.jdbc.odbc.JdbcOdbcDriver | jdbc:odbcLdatabase_name | jdbc-odbcBridge |
com.informix.jdbc.IfxDriver | jdbc:informix-sqli://ip:port/dbName:informixserver=sid | informix-DB |
- DB Connection 구조
- 2Tier - 클라이언트로서의 자바프로그램(JSP)이 직접 DB 서버로 접근하여 데이터를 액세스하는 구조
- 3Tier - 자바 프로그램과 데이터베이스 서버 사이에 미들웨어 계층이 존재하는 구조
미들웨어 계층은 비즈니스 로직 구현, 트랜잭션 처리, 리소스 관리 등을 담당함
- JDBC
- Java DataBase Connectivity
- 자바 언어로 다양한 종류의 관계형 데이터베이스에 접속하고 SQL문을 수행하여 처리하고자 할 때 사용되는 표준 SQL 인터페이스 API
- 원래라면 DB마다 연결 방식과 통신 규격이 따로 있기 때문에 프로그램을 DB와 연결한다면, 해당 DB와 관련된 기술적 내용을 배우고 DB가 변경될 시 많은 변경사항이 존재함
- 하지만 각 DBMS에 맞는 JDBC를 받아주게 되면 쉽게 DBMS를 변경할 수 있게 됨
👉 DBMS 종류에 상관 없이 하나의 JDBC API를 사용해서 데이터베이스 작업을 처리할 수 있게 됨 - 자바 애플리케이션에서 데이터베이스에 접근하기 위해서는 JDBC API를 이용해서 데이터베이스에 접근하고, JDBC API는 JDBC 드라이버를 거쳐 데이터베이스와 통신함
- JDBC 드라이버
- 자바 프로그램의 요청을 DBMS가 이해할 수 있는 프로토콜로 변환해주는 클라이언트 사이드 어댑터
- 각각의 DBMS는 자신에게 알맞은 JDBC 드라이버를 제공하고 있음
Client-Side Adapter
- Adapter Pattern 어댑터 패턴으로 개발된 Adapter
- 어댑터 패턴: 클래스의 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하는 패턴
👉 JDBC 드라이버는 DB가 달라도 어댑터 패턴으로 개발된 어댑터로 동일한 함수로 동일하게 동작되게 해줌
- JDBC 실행 과정
- 첫 번째, DB 벤더에 맞는 드라이버 로드
- 두 번째, DB 서버의 IP, ID, PW 등을 DriverManager 클래스의 getConnection() 메소드를 사용하여 Connection 객체 생성
- 세 번째, Connection에서 PreparedStatement 객체를 받음
- 네 번째, executeQuery를 수행
- 다섯 번째, ResultSet 객체를 받아 데이터를 처리
- 마지막, 사용하였던 ResultSet, PreparedStatement, Connection을 close
[ 예시 ]
package spms.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import spms.util.DBConnectionPool;
import spms.vo.Member;
/* Dao (Data Access Object)
* 데이터베이스는 연결하여 데이터를 입출력을 담당하는 클래스
* 이 클래스로 만들어진 오브젝트를 Dao라고 부른다.
* */
public class MemberDao {
private String strSelectList =
"SELECT mno,mname,email,cre_date FROM members ORDER BY mno ASC";
DBConnectionPool connPool;
public void setDBConnectionPool(DBConnectionPool connPool) {
this.connPool = connPool;
}
/*
* Connection 객체 1개로 여러 메서드가 각각의 서블릿에서 호출되면
* rollback시 다른 명령에도 영향을 주어서 취소가 되므로
* 이제 ConnectionPool을 사용해서 독립적인 명령 처리가 되도록 한다.
*
Connection connection;
public void setConnection(Connection connection) {
this.connection = connection;
}
*/
// MemberListServlet에서 필요
public List<Member> selectList() throws Exception{
Connection connection = null; // 추가
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 커넥션풀에서 객체를 빌려옴
connection = this.connPool.getConnection(); // 추가
stmt = connection.prepareStatement(strSelectList);
rs = stmt.executeQuery();
List<Member> members = new ArrayList<>();
while(rs.next()) {
members.add(new Member()
.setNo(rs.getInt("mno"))
.setName(rs.getString("mname"))
.setEmail(rs.getString("email"))
.setCreatedDate(rs.getDate("cre_date"))
);
}
return members;
}catch(Exception e) {
throw e;
}finally {
try {if(rs!=null) rs.close();} catch(Exception e) {}
try {if(stmt!=null) stmt.close();} catch(Exception e) {}
// 커넥션풀에서 빌려온 Connection 객체를 반납함
if(connection != null) connPool.returnConnection(connection);
}
}
}
- getConnection()
- DriverManager.getConnection()은 실제 자바 프로그램과 데이터베이스를 네트워크 상에서 연결해주는 메소드
- 연결에 성공하면 DB와의 연결 상태를 Connection 객체로 표현하여 반환함
- 가장 부하가 많이 걸리는 과정
- Connection
- DB 연결 객체
- 데이터베이스로의 연결 기능을 제공하며, Statement 객체를 생성하는 기능 제공
- SQL문을 데이터베이스에 전송하거나, 이러한 SQL문을 커밋하거나 롤백하는 데 사용
- 보통 Connection 하나 당 트랜잭션 하나를 관리함
: Mybatis의 SqlSession, Hibernate의 TransactionManager 등의 Close가 이루어지면 Connection을 ConnectionPool에 반납함
- Statement 또는 PreparedStatement
: SQL문 실행 객체 - ResultSet
: 쿼리문의 결과를 가지는 객체 - Driver
: 각 JDBC Driver 벤더에서 구현해야 하는 인터페이스 - DriverManager
: 사용될 드라이버를 등록하거나 등록을 해제하는 기능과 DB를 연결하는 기능을 수행함
- Connection Pool
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
sql = "SELECT * FROM t_board";
// 1. 드라이버 연결 DB 커넥션 객체를 얻음
conn = DriverManager.getConnection(DBURL, DBUSER, DBPW);
// 2. 쿼리 수행을 위한 PreparedStatement 객체 생성
pstmt = conn.createStatement();
// 3. executeQuery: 쿼리 실행 후
// ResultSet: DB 레코드 ResultSet에 객체가 담김
rs = pstmt.executeQuery(sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
rs.close();
pstmt.close();
conn.close();
}
자바에서 DB에 직접 연결해서 처리하는 경우 JDBC Driver를 로드하고 커넥션 객체를 받아와야 함
👉 매번 사용자가 요청을 할 때마다 드라이버를 로드하고 커넥션 객체를 생성해 연결하고 종료하므로 매우 비효율적임
👉 이런 문제를 해결하기 위해서 커넥션 풀을 사용함
2. DBCP 데이터베이스 커넥션 풀이란?
- 커넥션 풀 DBCP의 개념
- 웹 컨테이너 WAS가 실행되면서 일정량의 Connection 객체를 미리 만들어서 pool에 저장했다가,
클라이언트 요청이 오면 Connection 객체를 빌려주고
해당 객체의 임무가 완료되면 다시 Connection 객체를 반납 받아서
pool에 저장하는 프로그래밍 기법
- 커넥션 풀 DBCP의 장점
- 클라이언트가 빠르게 DB에 접속이 가능
: DB 접속 설정 객체를 미리 만들어 연결하여 메모리 상에 등록해 놓기 때문에 불필요한 작업(커넥션 생성, 삭제)이 사라지므로 - DB Connection 수를 제한할 수 있어서 과도한 접속으로 인한 서버 자원 고갈 방지가 가능함
- DB 접속 모듈을 공통화하여 DB 서버의 환경이 바뀔 경우 쉬운 유지 보수가 가능함
- 연결이 끝난 Connection을 재사용 👉 새로 객체를 만드는 비용을 줄일 수 있음
- 커넥션 풀 DBCP의 종류
- commons-dbcp: 아파치에서 제공하는 대표적인 connection pool 라이브러리
- tomcat-jdbc-pool: Tomcat에 내장되어 있으며, Apache Commons DBCP 라이브러리를 기반으로 만들어짐
- HikariCP: 스프링 부트 2.0부터 default JDBC Connection Pool로 사용되며, zero-overhead의 특징을 가지고 있음
overhead: 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간 및 메모리
- 커넥션 풀 DBCP의 유의사항
🖊️동시 접속자가 많을 경우
너무 많은 DB 접근이 발생할 경우에는 커넥션은 한정되어 있기 때문에 쓸 수 있는 커넥션이 반납될 때까지 기다려야 함
너무 많은 커넥션을 생성할 시에는 커넥션 또한 객체이므로 많은 메모리를 차지하게 되고, 프로그램의 성능을 떨어뜨리는 원인이 됨
👉 WAS에서 커넥션 풀을 크게 설정하면 메모리 소모가 큰 대신 사용자가 대기 시간이 줄어들고,
반대로 커넥션 풀을 작게 설정하면 그만큼 대기 시간이 길어짐
👉 사용량에 따라 적정량의 커넥션 객체를 생성해 두어야 함
🖊️Connection Pool이 커지면 성능은 무조건 좋아질까?
👉 No❗ Connection의 주체는 Thread이므로 Thread와 함께 고려해야 함
- Thread Pool 크기 < Connection Pool 크기라면?
: Thread Pool에서 트랜잭션을 처리하는 Thread가 사용하는 Connection 외에 남는 Connection은 실질적으로 메모리 공간만 차지하게 됨 - Thread Pool 크기와 Connection Pool 모두 크기가 증가하면?
- Thread 증가로 인해 더 많은 Context Switching이 발생함
- Disk 경합 측면에서는 성능 한계가 발생함- 데이터베이스는 하드 디스크 하나 당 하나의 I/O를 처리하므로 블로킹이 발생함
- 👉 특정 시점부터는 성능적인 증가가 Disk 병목으로 인해 미비해짐
👉 Connection은 Thread와 어느 정도 일치함
Connection이 많다는 의미는 데이터베이스 서버가 Thread를 많이 사용하는 것을 의미함
Context Switching으로 인한 오버헤드가 더 많이 발생하므로 Connection Pool을 아무리 늘리더라도 성능적인 한계가 존재
요약
- JDBC는 자바 애플리케이션이 데이터베이스에 접근할 수 있도록 JAVA에서 제공하는 API
- 하나의 JDBC로 어떤 DBMS든 각 벤더마다 제공되는 JDBC 드라이버를 통해 연결할 수 있음
- 커넥션 풀이란 JDBC 실행 과정 중에서 생성되어야 할 Connection 객체를 미리 만들어서 pool이란 곳에서 저장을 해두는 기법
- 장점: 불필요한 과정(Connection 객체를 생성, 삭제)을 줄여서 성능을 높일 수 있음
- WAS에서 커넥션 풀을 크게 설정하면 메모리 크기가 큰 대신 사용자 대기 시간이 줄어듦
반대로 커넥션 풀을 작게 설정하면 메모리 크기가 작은 대신 사용자 대기 시간이 길어짐
👉 사용량에 따라 적정량의 커넥션 객체를 생성해두어야 함
출처
'Computer Science > DB' 카테고리의 다른 글
[정보처리기사] SQL 응용 - 기본 SQL 작성하기 (0) | 2024.04.23 |
---|---|
[DB] 조인 Join (2) | 2024.04.03 |
[DB] B-tree, B+tree (0) | 2024.04.01 |
[DB] 인덱스 index (0) | 2024.04.01 |
[DB] 트리거 Trigger (0) | 2024.03.28 |