JDBC Connection ์ ๋ํ ์ดํด, HikariCP ์ค์ ํ
by JiwonDevJDBC๊ฐ ๋ฌด์์ธ์ง ์์ ๋ชจ๋ฅธ๋ค๋ฉด [10๋ถ ํ ์ฝํก] ์ฝ์ฝ๋ฅ์ JDBC ์์์ ํ๋ฒ ๋ณด๊ณ ์ค์๋ฉด ์ข์ต๋๋ค.
๐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์์ ๊ฒฐ๊ตญ JDBC
JVM์ ์ฌ์ฉํ๋ค๋ฉด ์คํ๋ง์ด๊ฑด JPA๋ฅผ ์ฐ๊ฑด ๊ฒฐ๊ตญ ๋ง์ง๋ง์ JDBC (Java Database Connectivity API)๋ฅผ ์ด์ฉํ์ฌ DB ์ ํต์ ํ๊ฒ ๋ฉ๋๋ค. ์ฐธ๊ณ ๋ก JDBC Driver๋ ์ธํฐํ์ด์ค ์ผ ๋ฟ ์ค์ ๊ตฌํ์ฒด๋ ๊ณต์ DB ๋ฒค๋์ฌ(Oracle, MS..)์์ ์ ๊ณตํฉ๋๋ค. ๋ง์ฝ ๋๋ง์ Driver๋ฅผ ๊ตฌํํ๊ณ ์ถ๋ค๋ฉด ๋์ผํ๊ฒ JDBC Driver ๊ตฌํ์ฒด๋ฅผ ๋ง๋ค์ด์ ๋ฑ๋กํ๋ฉด ๋ฉ๋๋ค.
try {
// JDBC 4.0 ๋ถํฐ๋ META-INF/services/java.sql.Driver๋ฅผ ์ฝ์ด DriverManager๋ฅผ ๋ฏธ๋ฆฌ ์์ฑํด์ค๋๋ค.
// ๋ฌผ๋ก Class.forName("com.mysql.cj.jdbc.Driver") ๋ฅผ ํธ์ถํด์ ์ง์ DriverManager์ ์ถ๊ฐํ ์๋ ์์ต๋๋ค.
connection = DriverManager.getConnection(jdbcUrl, username, password)
println("Database connection established.")
// Statement ์์ฑ
statement = connection.createStatement()
// SQL ์ฟผ๋ฆฌ ์คํ
val sql = "SELECT * FROM your_table"
resultSet = statement.executeQuery(sql)
// ๊ฒฐ๊ณผ ์ฒ๋ฆฌ
while (resultSet.next()) {
// ์ฒซ ๋ฒ์งธ ์ปฌ๋ผ ๊ฐ์ String์ผ๋ก ์ฝ๊ธฐ
val firstColumnValue = resultSet.getString(1)
println(firstColumnValue)
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
// DB ์ปค๋ฅ์
์ ๋ซ์์ค์ผ ํฉ๋๋ค. Java7 ๋ถํฐ๋ try-resource ๋ฌธ (kotlin ์์ use)๋ฅผ ์ฌ์ฉํ๋ฉด ํธํฉ๋๋ค.
resultSet?.close()
statement?.close()
connection?.close()
}
๐ DB ํธ๋์ญ์ ์ ์ด๋ป๊ฒ ๊ฑฐ๋ ๊ฑธ๊น์?
๋๋ถ๋ถ์ DBMS ๋ AutoCommit ํธ๋์ญ์ ๋ชจ๋์ ๋ช ์์ ์ธ ํธ๋์ญ์ ๋ชจ๋(BEGIN-COMMIT-ROLLBACK) ๋ ๋ค ์ ๊ณตํฉ๋๋ค. ๋น์ฐํ๊ฑฐ์ง๋ง DB์์ ๋ชจ๋ ์์ ์ ํธ๋์ญ์ ๋ด์์ ์ด๋ฃจ์ด์ง๋๋ค. ํธ๋์ญ์ ์ ๊ฑธ์ง ์์๋๋ผ๋ AutoCommit์ ์ํด ์์ ์๋ฃ ํ Commit์ด ์คํ ๋ฉ๋๋ค.
JDBC์ ๊ฒฝ์ฐ ํธ๋์ญ์ ๋ฒ์๋ฅผ ์ง์ ํ ๋ ๋ณ๋์ API, ์๋ฅผ ๋ค์ด BeginTransaction() ๊ฐ์ ๋ฉ์๋๋ฅผ ๋ฐ๋ก ์ ๊ณตํ์ง์์ต๋๋ค. ๋์ Connection.setAutoCommit(false) ๋ฅผ ์ด์ฉํด ํธ๋์ญ์ ์ ์ง์ ํ ์ ์๋๋ก ์ ๊ณตํฉ๋๋ค.
์ด ๋ ํ๊ฐ์ง ์ ์ํด์ผํ ์ ์, setAutoCommit์ ๋ฐ๊ฟ ๋ JDBC ๋ด๋ถ์๋ง ๋-๋ฑ ์ ์ฉ๋๋๊ฒ ์๋๋ผ DBMS์ ์ฟผ๋ฆฌ๋ก ์์ฒญํด์ผํ๋ค๋ ์ ์ ๋๋ค. ์ด๋ฅผ ๋ฌด์๋ฏธํ๊ฒ ๊ณ์ ๋ณ๊ฒฝํ๋ค๋ฉด ํ์ ์ด์์ ํธ๋ํฝ๊ณผ DB ๋ถํ๊ฐ ๋ฐ์๋ ์ ์์ต๋๋ค. ๋ฌผ๋ก ์คํ๋ง์ ์ด๋ค๋ฉด DataSourceTranscationManager ์์ ์ด๋ฏธ ์ต์ ํ ๋์ด์๊ณ HikariDataSource ์์๋ autoCommit์ ๊ด๋ฆฌํด์ฃผ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐ์๊ฐ ์ ๊ฒฝ ์ธ ์ผ์ ์๊ธดํฉ๋๋ค.
๋ง์ฝ Reader, Writer DB๋ฅผ ๋ถ๋ฆฌํด์ ์ฌ์ฉํ๋ค๋ฉด ์๋์ ๊ฐ์ด ๊ธฐ๋ณธ๊ฐ์ ๋ค๋ฅด๊ฒ ์ค์ ํด์ฃผ๊ธฐ๋ ํฉ๋๋ค.
spring:
datasource:
maindb:
writer:
driver-class-name: org.postgresql.Driver
auto-commit: false # writer๋ ์ง์ ํธ๋์ญ์
์ ๊ฑธ์ผ์ด ๋ง์ผ๋ ๊ธฐ๋ณธ๊ฐ false
connection-timeout: 3000
reader:
driver-class-name: org.postgresql.Driver
auto-commit: true # read-only๋ ํธ๋์ญ์
์ ๊ฑธ ์ผ์ด ์์ผ๋ ๊ธฐ๋ณธ๊ฐ true
connection-timeout: 3000
๐ JDBC API๋ ์ด๋ป๊ฒ ๋์ํ ๊น์?
JDBC API ๋ฅผ ์์ธํ๊ฒ ์ดํด๋ณด๋ฉด ํฌ๊ฒ JDBC Driver์ DataSource๋ก ๋๋ ์ ์์ต๋๋ค. ์ฐธ๊ณ ๋ก Repository(DAO, Data Access Object)๋ ๊ฐ๋ฐ์๊ฐ ์ง์ ์์ฑํ๋ ์ฝ๋๋ฅผ ์๋ฏธํฉ๋๋ค.
- JDBC Driver ์ธํฐํ์ด์ค๋ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋คํธ์ํฌ ์ฐ๊ฒฐ์ ๋ด๋นํฉ๋๋ค.
- DataSource ์ธํฐํ์ด์ค๋ ๊ฐ์ข ์ค์ ๋ฐ ์ปค๋ฅ์ ํ์ ๋ด๋นํฉ๋๋ค.
- ์ฐธ๊ณ ๋ก ์๋ฌด๋ฐ ์ค์ ์์ด ์ฐ์ต์ฉ์ผ๋ก ๋จ์ ์ฐ๊ฒฐ์ ํด๋ณผ ๋๋ DataSource ๋์ DriverManager ๋ฅผ ์ง์ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
- JDBC Driver
์๋ฐ์์ Driver ์ธํฐํ์ด์ค๋ก ์ ๊ณต๋ฉ๋๋ค. ์ง์ ์ฌ์ฉํ์ง์๊ณ DataSource๋ฅผ ํตํด ์ฌ์ฉํ๋ฉฐ ์ด๋ ํน์ DB์ ์ค์ง์ ์ธ ํต์ ์ ๊ตฌํํ ๋ถ๋ถ์ ๋๋ค. Driver ๊ตฌํ์ฒด๋ ๊ณต์ ๋ฒค๋์ฌ(ex Oracle, MS)๊ฐ ๊ตฌํํ ์ต์ ํ๋ ์ฝ๋๋ฅผ ์ด์ฉํฉ๋๋ค.
- DataSource
* ๋น์ฐํ๊ฑฐ์ง๋ง DriverManager ๋ด๋ถ ์ฝ๋์๋ DataSource ๋ ์กด์ฌํ์ง ์์ต๋๋ค. ๊ทธ๋์ ์ด๋ฏธ ์กด์ฌํ๋ ์ปค๋ฅ์ ํ ๊ฐ์ฒด๋ฅผ ์ ์ฉํ ์ ์๋๋ฐ, Spring์ ์ฌ์ฉํ๋ค๋ฉด DriverManagerDataSource๋ฅผ ์ด์ฉํ๋ฉด ์์ฝ๊ฒ DriverManager ์ ์ปค๋ฅ์ ํ์ ๋ถ์ฌ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์๋ฐ์์ DataSource ์ธํฐํ์ด์ค๋ก ์ ๊ณต๋ฉ๋๋ค. ์ด๋ JDBC Driver๊ฐ ๊ฐ์ ธ์จ DB ์ปค๋ฅ์ ๊ณผ ์ปค๋ฅ์ ํ์ ๊ด๋ฆฌํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. DataSource์ ๊ตฌํ์ฒด ๋ํ DB ๋ฒค๋์ฌ ๋๋ ์๋ํํฐ์ฌ๋ฅผ ํตํด ์ ๊ณต๋ฉ๋๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ด๋ฆ | JDBC DataSource ํจํค์ง ๊ฒฝ๋ก(=์ด๋ฆ) |
Commons DBCP ( * Apache DBCP ) https://d2.naver.com/helloworld/5102792 |
org.apache.commons.dbcp2.BasicDataSource |
Tomcat JDBC (* ํฐ์บฃ ๋ด์ฅ DBCP) | org.apache.tomcat.jdbc.pool.DataSource |
DRUID ( * ์๋ฆฌ๋ฐ๋ฐ DBCP ) | com.alibaba.druid.pool.DruidDataSource |
HikariCP ( * Spring ๊ธฐ๋ณธ DBCP ) | com.zaxxer.hikari.HikariDataSource |
๐ Connection Timeout์ ์ ๋ฐ์ํ๋๊ฑธ๊น์?
JDBC Driver๋ ๊ฒฐ๊ตญ ๋คํธ์ํฌ๋ฅผ ํตํด DB ์๋ฒ์ ํต์ ํ๋ ํด๋ผ์ด์ธํธ์ ๋๋ค. ๋ณดํต ์์ผ์ ์ด์ฉํ TCP/IP ์ฐ๊ฒฐ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์ฝ๊ธฐ ๋์ค Connection Timeout, Socket Timeout์ด ๋ฐ์ํ ์ ์์ต๋๋ค. DB ๊ตฌํ์ฒด๋ง๋ค ๋ค๋ฅด๊ฒ ์ง๋ง ๋ณดํต ์ปค๋ฅ์ ์ด ๋์ด์ง ๊ฒฝ์ฐ ์คํ์ค์ธ ์ฟผ๋ฆฌ๊ฐ ์ทจ์๋๊ณ ํธ๋์ญ์ ์ด ๋กค๋ฐฑ๋ฉ๋๋ค.
- Connection Timeout : ์ต์ด ์ฐ๊ฒฐ์ ๋งบ๋ ์๊ฐ(์๊ณ์น, threshold)๋ฅผ ์ด๊ณผ๋ ๊ฒฝ์ฐ
- Socket Timeout : ์ฐ๊ฒฐ์ ์ฑ๊ณตํ์ผ๋ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ๋ ๊ฐ๋ณ ํจํท ์๋ต์๊ฐ์ ์ด๊ณผํ ๊ฒฝ์ฐ
์ฌ๊ธฐ์ ์ถ๊ฐ๋ก JDBC Driver์์ Statement Timeout ๊น์ง ์ ๊ณตํฉ๋๋ค.
SocketTime์ด ๋ฌผ๋ฆฌ์ ์ธ ์ฐ๊ฒฐ์์ ๋คํธ์ํฌ ์ฅ์ ๋ฅผ ์๋ฏธํ๋ค๋ฉด, Statement Timeout์ DB์์ ์ํ๋๋ ํ๋์ SQL Statement ์ํ์๊ฐ์ ๋ํ ํ์ ์์์ ์ง์ ํ ์ ์์ต๋๋ค. ์ฌ๋ด์ผ๋ก Spring TransactionManager๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ํธ๋์ญ์ timeout ๋ ์ถ๊ฐ๋ก ์ ๊ณตํฉ๋๋ค.
์ฐธ๊ณ ๋ก SQL ์คํ์๊ฐ์ ์ ํ์ ๊ฑธ๊ธฐ์ํด Statement Timeout์ ์ค์ ํ ๊ฒฝ์ฐ, ๋น์ฐํ Socket Timeout ์ ๋ ํฌ๊ฒ ์ก์์ค์ผํฉ๋๋ค. ์ด์ฐจํผ ์์ผ์ด ๋๊ธฐ๋ฉด ๋ด๋ถ์์ ์ด๋ป๊ฒ ์ค์ ํ๋ ํด๋น ํธ๋์ญ์ ์ ๋กค๋ฐฑ๋๋๊น์.
๐ DB Connection Pool (DBCP) ๋ ์ ์ฌ์ฉํ๋์?
DB ์ปค๋ฅ์ ์ ์ป๋ ๊ณผ์
1. [์ดํ๋ฆฌ์ผ์ด์ ์๋ฒ]๋ JDBC ์ธํฐํ์ด์ค๋ฅผ ์ด์ฉํด ์ค์ DB ๋๋ผ์ด๋ฒ๋ฅผ ์ฌ์ฉํ์ฌ ์ปค๋ฅ์ ์ ์กฐํํ๋ค.
2. ์์ฒญ ๋ฐ์ DB ๋๋ผ์ด๋ฒ๋ TCP/IP ์ปค๋ฅ์ ์ ์ฐ๊ฒฐํ๋ค. (TCP 3 Way-Handshake)
3. ์ฐ๊ฒฐ๋ ์ปค๋ฅ์ ์ผ๋ก [DB ์๋ฒ]์ ๋ก๊ทธ์ธ ์์ฒญ ๋ฐ ์ธ์ ๋ถ๊ฐ์ ๋ณด๋ฅผ ์ ๋ฌํ๋ค.
4. ์์ฒญ๋ฐ์ [DB ์๋ฒ]๋ ์ธ์ฆ์ ์๋ฃํ๊ณ [์ดํ๋ฆฌ์ผ์ด์ ์๋ฒ]์ ํต์ ํ DB ์ธ์ ์ ๋ด๋ถ์ ์ผ๋ก ์์ฑํ๋ค.
5. [DB ์๋ฒ]๋ ์ปค๋ฅ์ ์์ฑ์ด ์๋ฃ๋์๋ค๋ ์๋ต์ ๋ณด๋ธ๋ค.
6. DB ๋๋ผ์ด๋ฒ๋ ์ฐ๊ฒฐ์ด ์๋ฃ๋์๋์ง ๊ฒ์ฆํ ํ, ์๋ก์ด Connection ๊ฐ์ฒด๋ฅผ [์ดํ๋ฆฌ์ผ์ด์ ์๋ฒ]์ ์ ๋ฌํ๋ค.
DB Connection Pool (์ดํ DBCP) ๋ฅผ ์ฐ๊ฒฐํ๊ณ ๊ฐ์ฒด๋ฅผ ์ด๊ธฐํํ๋ ๊ณผ์ ์ ๋น์ฉ๋ ๋ง์ด ๋ค๊ณ ๊ทธ ๊ณผ์ ์์ฒด๋ ๋ณต์กํฉ๋๋ค. ๊ทธ๋์ ๋งค๋ฒ ์๋กญ๊ฒ ์ฐ๊ฒฐํ์ง ์๊ณ ์ปค๋ฅ์ ํ(= ์ปค๋ฅ์ ์ ์ฅ์)๋ฅผ ์ด์ฉํด ๋ฏธ๋ฆฌ ์ปค๋ฅ์ ์ ๋ง๋ค์ด๋๊ณ ์ฌ์ฌ์ฉํ๊ฒ๋ฉ๋๋ค. ๋ฌผ๋ก ๊ฐ๋ฐ์๊ฐ ์ง์ Map์ ๋ง๋ค์ด์ ๊ด๋ฆฌํด๋ ๋ฉ๋๋ค๋ง ๋ณดํต์ ์ ๋ง๋ค์ด์ง ์ปค๋ฅ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํฉ๋๋ค. ์คํ๋ง์ ๊ธฐ๋ณธ์ผ๋ก HikariCP ๋ฅผ ์ฌ์ฉํ๋๋ฐ ๋ฒค์น๋งํฌ ๋งํฌ๋ฅผ ๋ณด๋ฉด ์ด๋ค ์ ์ด ์ข์์ ๊ธฐ๋ณธ์ผ๋ก ์ฑํ๋์๋์ง ์ ์ ์์ต๋๋ค.
Java ์ปค๋ฅ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฒฝ์ฐ ๋๋ถ๋ถ ๋ฒค๋์ฌ์ DataSource๋ฅผ ๋ํํ์ฌ ์ ๊ณตํฉ๋๋ค. ์๋ฅผ ๋ค์ด HikariCP๋ผ๋ฉด HikariDataSource ์ ์ฌ์ฉํ DB๋ฅผ ์ค์ ํ๋ฉด ๋ฐ๋ก ์ฌ์ฉ๊ฐ๋ฅํ๊ฒ ๊ตฌ์ฑํด๋ก๋๋ค. ์ด๋ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ 2๊ฐ์ง๊ฐ ์๋๋ฐ ๋ณดํต jdbcUrl๋ก ๋ง์ด ์ฐ๊ฒฐํฉ๋๋ค.
- < JDBC URL + DB Driver > ์ค์
jdbcUrl: jdbc:mysql://localhost:3306/world?serverTimeZone=UTC&CharacterEncoding=UTF-8 - < DataSource ๊ตฌํ์ฒด > className ์ค์
dataSourceClassName: oracle.jdbc.pool.OracleDataSource
- DataSource ๊ตฌํ์ฒด ์ค์ (DataSource-ClassName ์ค์ )
DataSource ๊ตฌํ์ฒด๋ฅผ ์ง์ ๋ช ์ํ์ฌ ์ปค๋ฅ์ ํ์ ์ค์ ํฉ๋๋ค. ํน์ DataSource ๊ตฌํ์ฒด๋ง ์๋ ์ค์ ์ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
// DataSourceClassName ์ค์ ์ com.zaxxer.hikari.util.DriverDataSource ๊ธฐ๋ฐ์ผ๋ก ๋์ํฉ๋๋ค.
HikariConfig config = new HikariConfig();
// PostgreSQL์ DataSource ๊ตฌํ์ฒด ํด๋์ค ์ด๋ฆ์ ์ค์
config.setDataSourceClassName("org.postgresql.ds.PGSimpleDataSource");
config.addDataSourceProperty("user", "user");
config.addDataSourceProperty("password", "password");
HikariDataSource dataSource = new HikariDataSource(config);
- ์๋ฐ ํ์ค JDBC URL + DB Driver (driver-class-name)
ํ์ค jdbcUrl์ ๊ทธ๋๋ก ์ฌ์ฉํด์ ์ค์ ํฉ๋๋ค. ์ง๊ด์ ์ด๊ณ ํธํด์ ๋ง์ด ์ฌ์ฉํ์ง๋ง ํน์ DB์๋ง ์๋ ์ค์ ์ ์ถ๊ฐํ๊ธฐ ์ด๋ ต์ต๋๋ค.
HikariConfig config = new HikariConfig();
// PostgreSQL ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํ๊ธฐ ์ํ JDBC URL ์ค์
String jdbcUrl = "jdbc:postgresql://localhost:5432/mydatabase";
config.setJdbcUrl(jdbcUrl);
HikariDataSource dataSource = new HikariDataSource(config);
์ฝ๋๋ก ๋ณด๋ฉด ์ด์ํ ์๋ ์๋๋ฐ ์คํ๋ง๋ถํธ์ ์๋๊ตฌ์ฑ์ ์ฌ์ฉํ๋ค๋ฉด ์๋์ ๊ฐ์ด yml๋ก ํธํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ฐ๋ DB ์์ฒด ์ค์ ์ผ๋ก ์ฐฉ๊ฐํ์๋ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ, ์ด๋ HikariDataSource์์ ํ๋ ์๋ฒ ํ์์์ ๊ฐ & ์ปค๋ฅ์ ํ ์ค์ ์ ๋๋ค.
spring:
datasource:
# ex) spring.datasource.driver-class-name → HikariConfig.setDriverClassName()
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/world?serverTimeZone=UTC&CharacterEncoding=UTF-8
username: root
password: your_password
hikari:
# ์ค๋ ๋๊ฐ HikariCP์ connection์ ์์ฒญํ๊ณ , ์ด๋ฅผ ๋๊ธฐํ๋ ์ต๋์๊ฐ์
๋๋ค. * DB timeout ์๋๋๋ค.
connection-timeout: 3000
# HikariCP ์ปค๋ฅ์
ํ์ ์ด๋ฆ.
pool-name: HikariCP-Writer
# ๊ธฐ๋ณธ์ผ๋ก ์ค์ ํ autoCommit ๊ฐ. ๋ณดํต read-only๋ true ๋ก, writer๋ false๋ก ์ค์ ํฉ๋๋ค.
auto-commit: false
# JDBC 4.0 ์ด์ ์๋ ๊ฐ DB๊ฐ Connection.isValid() ๊ฐ์ ๊ฑธ ์ง์ํ์ง ์์์ ์ ์ฉํ๊ฒ ์ฌ์ฉํ๋ค.
# ๋ฌผ๋ก ์ง๊ธ์ ์ ~ํ ํ์ ์๋ ๊ธฐ๋ฅ
connection-init-sql: SET TIME ZONE 'UTC' # ์ปค๋ฅ์
์์ฑํ ๋ ๋ง๋ค ์ฟผ๋ฆฌ
connection-test-query: SELECT 1 # ์๋ก์ด ์ปค๋ฅ์
์ ์ฃผ๊ธฐ ์ DB ํฌ์ค์ฒดํฌ ํ๋ ์ฟผ๋ฆฌ
# ์๋ก์ด ์ปค๋ฅ์
์ ์ฃผ๊ธฐ ์ DB ํฌ์ค์ฒดํฌ timeout ์๊ฐ, ์ฐธ๊ณ ๋ก connection-init-sql์๋ ๊ฐ์ด ์ ์ฉ๋จ
validation-timeout: 2000
# ํ์์ ์ ์ง๋๋ ์ต์ํ์ ์ ํด ์ปค๋ฅ์
์.
minimum-idle: 10
# ํ์์ ๊ด๋ฆฌํ ์ ์๋ ์ต๋ ์ปค๋ฅ์
์.
maximum-pool-size: 50
# ์ปค๋ฅ์
์ด ์ ํด ์ํ๋ก ์์ ์ ์๋ ์ต๋ ์๊ฐ(๋ฐ๋ฆฌ์ด), DB ์์ฒด ์ปค๋ฅ์
์๊ฐ ๋ถ์กฑํ๋ค๋ฉด ์๊ฐ์ ์ค์ฌ์ผํจ
idle-timeout: 30000
# ํ์ ์ปค๋ฅ์
์ด ์์ฑ๋ ํ ์์ ์ ์๋ ์ต๋์๊ฐ (๋ฐ๋ฆฌ์ด), DB ์์ฒด ์ปค๋ฅ์
์๊ฐ ๋ถ์กฑํ๋ค๋ฉด ์๊ฐ์ ์ค์ฌ์ผํจ
max-lifetime: 50000
์ฐธ๊ณ ๋ก reader, writer๋ฅผ ๋ฐ๋ก ์ฌ์ฉํ๋ค๋ฉด ์๋์ ๊ฐ์ด @ConfigurationProperties๋ฅผ ํ์ฉํด ๊ฐ๊ฐ ๋ฐ๋ก ์ค์ ํด์ฃผ๊ธฐ๋ ํฉ๋๋ค.
๐ ์ปค๋ฅ์ ํ(HikariCP) ์ ์ด๋ป๊ฒ ์ค์ ํ๋๊ฒ ์ข์๊น์?
HikariCP ๊ธฐ์ค์ผ๋ก ์ค๋ช ํ๋ฉด ์ถ์ฒ๊ฐ์ ์๋์ ๊ฐ์ต๋๋ค.
HikariCP ์ค์ | ์ค๋ช | ์ถ์ฒ๊ฐ |
maximum-pool-size | ์ปค๋ฅ์ ํ์ ์ต๋ ํฌ๊ธฐ | (๊ธฐ๋ณธ๊ฐ 10๊ฐ) ์ถ์ฒ๊ฐ 50 ๊ฐ ์ํฉ์ ๋ฐ๋ผ ์กฐ์ ํด์ผํ๋ค. |
minimum-idle | ์ปค๋ฅ์
ํ์ ์ต์ ํฌ๊ธฐ ์ ํํ๋ ํ์์ ์ ์ง๋ ์ต์ ์ ํ(Idle) ๊ฐ์ |
(๊ธฐ๋ณธ๊ฐ 10๊ฐ) ์ค์ ํ์ง ์๋๋ค. |
โ
์๋ต์๋๊ฐ ์ค์ํ ์์คํ
์ด๋ผ๋ฉด max ์ min ์ ๋์ผํ๊ฒ ๋ง์ถฐ ํญ์ ์ปค๋ฅ์
์ด ์ด์์๋๋ก ์ ์งํ๋ค. โ pool size์ ๊ฒฝ์ฐ ์๋ฒ์ ์ต๋ ์ค๋ ๋ ์๋ฅผ ์ ์ ํ๊ฒ ์ง์ ํด์ผํ๋ค. ์ปค๋ฅ์ ๋ํ Pool Locking ์ํ๊ฐ ๋์ด ๋ฐ๋๋ฝ์ด ๋ฐ์ํ ์ ์๋ค. *๊ธ ํ๋จ์ ์ถ๊ฐ ์ค๋ช ์์ |
||
connection-timeout | HikariCP ์ปค๋ฅ์
์์ฒญ ํ ๋๊ธฐํ๋ ์๊ฐ (DB ์ค์ ๊ณผ๋ ๊ด๋ จ ์๋ค) ์ฆ, ์ด๋ ๋ค๋ฅธ ๋ชจ๋ ๋๊ธฐ์๊ฐ์ ํฌํจํ๊ธฐ์ statement-timeout ๊ณผ validation-timeout์ ๊ณ ๋ คํด์ ์ง์ ํด์ผํ๋ค. |
(๊ธฐ๋ณธ๊ฐ 30์ด) ์ถ์ฒ๊ฐ 3,000ms |
max-lifetime | ์ปค๋ฅ์
ํ์์ ๋๊ธฐํ ์ ์๋ ์ปค๋ฅ์
์ ์ต๋ ์๋ช
์ฃผ๊ธฐ(์๊ฐ) |
(๊ธฐ๋ณธ๊ฐ 30๋ถ) ์ถ์ฒ๊ฐ 50,000ms DB์ wait_timeout (idle_transaction_session_timeout) ๋ณด๋ค ๋ฐ๋์ ์๊ฒ ์ค์ ํด์ผ ์๋ฏธ๊ฐ ์๋ค. |
idle-timeout | ๋๊ณ ์๋ (idle) ์ปค๋ฅ์ ์ด ์๋ Close ๋๊ธฐ ์ ๋๊ธฐ์๊ฐ | ์ถ์ฒ๊ฐ 50,000ms pool size ๋ฅผ ๊ณ ์ ํด์ ์ฌ์ฉํ๋ค๋ฉด 0 (๋ฌดํ)์ผ๋ก ์ค์ ํ๋ค. |
โ
max-lifetime ๊ณผ idle-timeout์ ๋๊ธฐ๋๋ผ๋ minimum-idle ๋ฅผ ์ด๊ณผํ ๊ฒฝ์ฐ๋ง ์ปค๋ฅ์
์ด ์ ๊ฑฐ๋ฉ๋๋ค. โ idle-timeout์ max-lifetime๋ณด๋ค ์์ ๊ฐ์ด์ด์ผ ์๋ฏธ์์ต๋๋ค. ์๋๋ฉด idle ์ํ๊ฐ ๋๊ธฐ ์ ์ปค๋ฅ์ ์ด ์ญ์ ๋์๋ค๊ฐ ์๋ก ์์ฑ๋ ํ ๋๊น์. |
||
keepalive-time | DB ๊ฐ ์ปค๋ฅ์
์ ์์ฒด์ ์ผ๋ก ๋์ง ์๋๋ก HikariCP๊ฐ DB ํฌ์ค์ฒดํฌ Connection.isValid() ๋ฅผ ํธ์ถํด์ฃผ๋ ์ต๋์๊ฐ์
๋๋ค. ์ฐธ๊ณ ๋ก 30,000ms ๋ณด๋ค ์๊ฒ ์ค์ ํ ์ ์๊ฒ ๋งํ์์ต๋๋ค. |
(๊ธฐ๋ณธ๊ฐ 60000ms) ๊ธฐ๋ณธ๊ฐ ์ฌ์ฉ ์๋ต ์๋๊ฐ ์ค์ํ๋ค๋ฉด 30,000ms |
validation-timeout | HikariCP ์์ ์ปค๋ฅ์
์ ์ฃผ๊ธฐ ์ DB ํฌ์ค์ฒดํฌ ์ ํ์์์, Connection.isValid() |
์ถ์ฒ๊ฐ 1000ms ์ดํ |
โ
DB ํฌ์ค์ฒดํฌ ์ฉ๋์ธ Connection.isValid() ๋ JDBC4.0 ๋ถํฐ ์ง์ํ๋ ๊ธฐ๋ฅ, ๊ทธ ์ด์ ์๋ connection-init-sql ๊ฐ์ ๊ฑธ๋ก ์ฌ์ฉํ๋๋ฐ ๊ตฌ์๋ ์ ๋ฌผ์ด๋ผ ์ฌ์ฉํ ์ผ์ด ์๋ค. ์ฐธ๊ณ ๋ก connection-init-sql์๋ validation-timeout์ด ๋์ผํ๊ฒ ๊ฑธ๋ฆฐ๋ค. |
||
autoCommit | ์์์๋ ์ค๋ช ํ auto-commit์ ๊ธฐ๋ณธ๊ฐ | Writer ์์
์ด ๋ง์๊ฒฝ์ฐ true Read ์์ ์ด ๋ง์ ๊ฒฝ์ฐ false |
DB ์ TCP ํต์ ์ค ๋ฐ์ํ๋ Connection Timeout ์ด๋ Socket Timeout (==Read Timeout) ์ ์ปค๋ฅ์ ํ๊ณผ๋ ๊ด๋ จ ์์ต๋๋ค. ํ์ํ๋ค๋ฉด ์ด๋ JDBC URL๋ก ์ง์ ์ค์ ํ ์ ์์ต๋๋ค.
# ๊ธฐ๋ณธ๊ฐ ์ค์ , ํน์ ์ฟผ๋ฆฌ๋ง ์ค์ ํ๊ณ ์ถ๋ค๋ฉด java.sql.Statement.setQueryTimeout(int timeout) ์ฌ์ฉ
spring:
datasource:
url: jdbc:mysql://hostname:3306/database?socketTimeout=10000&connectTimeout=10000
JDBC์์ ๋ฐ๋ก ์ ๊ณตํ๋ Statement Timeout์ Statement.setQueryTimeout() ๋ฉ์๋๋ก ์ง์ ๊ฑธ ์ ์์ต๋๋ค.
๋ํ Spring @Transaction(timeout=...)์ ์ฌ์ฉํ๋ค๋ฉด, ์คํ๋ง์์ ์ ๊ณตํ๋ Transaction Timeout๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๐ Connection Pool ๊ณผ ์ค๋ ๋์ ์๊ด๊ด๊ณ ( HikariCP ๋ฐ๋๋ฝ )
connection pool size์ ๊ฒฝ์ฐ ์๋ฒ์ ์ต๋ ์ค๋ ๋ ์๋ฅผ ์ ์ ํ๊ฒ ์ง์ ํด์ฃผ์ด์ผ ํฉ๋๋ค. ์๋๋ฉด Pool Locking ์ผ๋ก HikariCP ์์ฒด ๋ฐ๋๋ฝ์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ๋คํํ๋ ์ด๋ ์ ์๋ ค์ง ์ด์๋ผ์ ์๋ ๊ณต์์ ๋ฐ๋ผ ๊ฐ์๋ฅผ ์ง์ ํด์ฃผ๋ฉด ์์ ํฉ๋๋ค.
Pool Locking์ ์๋์ ๊ฐ์ ์ํฉ์์ ๋ฐ์ํ ์ ์์ต๋๋ค.
1. ํ์ฌ ํ ํธ๋์ญ์ (ํ๋์ ์ค๋ ๋)์์ ์ปค๋ฅ์ ์ ๋ฌผ๊ณ ์๋ ์ํ๋ก, ์ปค๋ฅ์ ์ ํ๋ ๋ ์ฌ์ฉํ๋ ค๊ณ ์๋ํจ
- ์๋ฅผ ๋ค์ด insert ํ ๋ id_auto_increment๋ฅผ ์ฌ์ฉํ์ง ์๋ ๊ฒฝ์ฐ ์๋ธ ํธ๋์ญ์ ์ผ๋ก ID ๋ฐ์์ค๋ ์ปค๋ฅ์ ์ถ๊ฐ ์์ฑ
2. ๊ทธ๋ฐ๋ฐ ์๋ฒ๋ฅผ ๋นก์ธ๊ฒ ๋๋ ค์ ํ์ ๋จ์ ์๋ ์ปค๋ฅ์ ์ด ์์.
3. ๋ชจ๋ ์ค๋ ๋๊ฐ ์ปค๋ฅ์ ์ 1๊ฐ์ฉ ๋ค๊ณ ์๋ก๊ฐ ์๋ก๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋ฐ๋๋ฝ ์์ฑ ^ใ ^
4. ์ด์ ์ปค๋ฅ์ ์ ์ป์ง ๋ชปํด์, HikariCP ๊ธฐ๋ณธ timeout์ธ 30์ด๋ฅผ ๋๊ฒจ ๋๋ถ๋ถ์ ์์ฒญ์ด rollback -> ๋ ์ฅ์ !
ํด๋น ํ์์ ๋ํด์๋ (2020 ๋ฐฐ๋ฌ์๋ฏผ์กฑ) HikariCP Dead lock์์ ๋ฒ์ด๋๊ธฐ (์ด๋ก ํธ) ๊ธ์์๋ ์์ธํ๊ฒ ํ์ธํ ์ ์์ต๋๋ค.
๐ ๋ ํผ๋ฐ์ค
(2022 ๋ท๋ง๋ธ ์์ง๋์ด๋ง) ๊ฒ์ ์๋ฒ ์์คํ
์ ์ํ JDBC์ Timeout ์ดํดํ๊ธฐ
(2022 ๋ท๋ง๋ธ ์์ง๋์ด๋ง) ๊ฒ์ ์๋ฒ ์์คํ
์ ์ํ HikariCP ์ต์
๋ฐ ๊ถ์ฅ ์ค์
(2020 ๋ฐฐ๋ฌ์๋ฏผ์กฑ) HikariCP Dead lock์์ ๋ฒ์ด๋๊ธฐ (์ด๋ก ํธ)
(2020 ๋ฐฐ๋ฌ์๋ฏผ์กฑ) HikariCP Dead lock์์ ๋ฒ์ด๋๊ธฐ (์ค์ ํธ)
(2015 ๋ค์ด๋ฒ D2) Commons DBCP ์ดํดํ๊ธฐ
'๐ฑBackend > JDBC & JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Spring DB ๊ธฐ์ ํํค์น๊ธฐ #2 (0) | 2024.01.11 |
---|---|
Spring DB ๊ธฐ์ ํํค์น๊ธฐ #1 (1) | 2023.12.31 |
์คํ๋งJPA์ ์์์ฑ์ปจํ ์คํธ (EntityManager) (0) | 2022.02.03 |
QueryDSL + JPA (0) | 2022.02.02 |
Spring Data JPA (0) | 2022.01.31 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev