์์์ ํ๋ฆ๋๋ก ์จ๋ณด๋ DB ํธ๋์ญ์ ์ด์ผ๊ธฐ
by JiwonDev
๐ฏ ๋ฌด๊ฒฐ์ฑ๊ณผ ์ ํฉ์ฑ?
๋ฌด๊ฒฐ์ฑ(Integrity) : ํ ์ด ์์ด ์จ์ ํจ. ๋ฐ์ดํฐ ๊ฐ์ด ์ ํํ ์ํ์ธ๊ฐ ํน์ ์์๋์๊ฑฐ๋ ์ด์ํ ๊ฐ์ด ๋ค์ด๊ฐ์์ง๋ ์๋๊ฐ?
์ ํฉ์ฑ(Consistency) : ๋ชจ๋ ํธ๋์ญ์ ์์ [ ๊ฐ์ ๋ฐ์ดํฐ๊ฐ ]์ด ๋ชจ์ ์์ด ์ผ์นํ๊ฐ
[ ๋ฌด๊ฒฐ์ฑ๊ณผ ์ ํฉ์ฑ์ด ๋์ฒด ๋ญ์ฃ ? ]
์ํ DB์ 'ํ๊ธธ๋' ์ด๋ผ๋ ๊ณ ๊ฐ์ ์์ก์ 0์ ์ด์์ด์ด์ผ ํ๋ค.
Case1
- ์ฃผ๋ฌธ์ ๋ณด ํ
์ด๋ธ์ ํ๊ธธ๋์ ์์ก์ -10 ์ด๋ค. (๋ฌด๊ฒฐ์ฑ์ด ๊นจ์ก๋ค)
- ํ์ง๋ง ๊ณ ๊ฐ์ ๋ณด ํ
์ด๋ธ์๋ ํ๊ธธ๋์ ์์ก์ -10์ด๋ค. (์ ํฉ์ฑ๋ง ์ผ์นํ๋ค.)
Case2
- ์ฃผ๋ฌธ์ ๋ณด ํ ์ด๋ธ์ ํ๊ธธ๋ ์์ก์ 10,000 ์ด๋ค. (๋ฌด๊ฒฐ์ฑ์ ๋ฌธ์ ์๋ค.)
- ํ์ง๋ง ๊ณ ๊ฐ์ ๋ณด ํ ์ด๋ธ์์์ ํ๊ธธ๋ ์์ก์ 2000 ์ด๋ค. (์ ํฉ์ฑ๋ง ๊นจ์ก๋ค.)
์ด๋ฌํ ๋ฌด๊ฒฐ์ฑ๊ณผ ์ ํฉ์ฑ์, ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํ
์ด๋ธ '์ ์ฝ์กฐ๊ฑด'์ผ๋ก ๋ง์ ์ ์๋ค.
๋ฌผ๋ก ์ ์ฝ์กฐ๊ฑด์ ๊ฑธ๋ฉด ๊ทธ๋งํผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฑ๋ฅ์ ๋๋น ์ง๊ณ , ํ
์ด๋ธ์ ์ ์ฐํ๊ฒ ๋ณ๊ฒฝํ๊ธฐ ์ด๋ ค์์ง๋ค.
์ํฐํฐ ๋ฌด๊ฒฐ์ฑ(Entity Integrity) | ์ํฐํฐ๋ ๊ฐ ์ธ์คํด์ค๋ฅผ ์ ์ผํ๊ฒ ์๋ณํ ์ ์๋ ์์ฑ์ด๋ ์์ฑ ๊ทธ๋ฃน์ ๊ฐ์ ธ์ผ ํ๋ค. |
๋๋ฉ์ธ ๋ฌด๊ฒฐ์ฑ(Domain Integrity) | ์นผ๋ผ ๋ฐ์ดํฐ ํ์ , ๊ธธ์ด, ์ ํจ ๊ฐ์ด ์ผ๊ด๋๊ฒ ์ ์ง๋์ด์ผ ํ๋ค. |
์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ(Referential Integrity) | ๋ฐ์ดํฐ ๋ชจ๋ธ์์ ์ ์๋ ์ค์ฒด ๊ฐ์ ๊ด๊ณ ์กฐ๊ฑด์ ์ ์งํ๋ ๊ฒ์ด๋ค. |
์ ๋ฌด ๋ฌด๊ฒฐ์ฑ(Business Integrity) | ๋ค์ํ๊ฒ ์ ์๋ ์ ์๋ ๋น์ฆ๋์ค ๊ท์น์ด ๋ฐ์ดํฐ์ ์ผ๋ก ์ผ๊ด์ฑ์ ์ ์งํ๋ ๊ฒ์ด๋ค. |
๐ฏ ํธ๋์ญ์ ?
ํธ๋์ญ์
์ด๋ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ํ๋ ACID ํ ์์
๋จ์์ด๋ค.
[ ACID ํ ์์
๋จ์๋ผ๋๊ฒ ๋ฌด์จ ๋ง์ด์ฃ ? ]
Atomicity(์์์ฑ) - ์์ ๋จ์, ์ฆ ํธ๋์ญ์ ์ ๋ ์ด์ ์์ ๋จ์๋ก ์ชผ๊ฐค ์ ์๋ค.
- ํ ํธ๋์ญ์ ๋ด์ ๋ชจ๋ ๋ช ๋ น์ ๋ฐ๋์ ์๋ฒฝํ ์ํ๋์ด์ผ ํ๋ฉฐ, ๋ชจ๋๊ฐ ์๋ฒฝํ ์ํ๋์ง ์๊ณ ์ด๋ํ๋๋ผ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ํธ๋์ญ์ ์ ๋ถ๊ฐ ์ทจ์๋์ด์ผ ํ๋ค. ๋ถ๋ถ ์๋ฃ๋ ๋ถ๊ฐ๋ฅํ๋ค.
- ๋ณดํต ํธ๋์ญ์
์ฑ๊ณต ์ฐ์ฐ์ Commit(์ปค๋ฐ), ์คํจ ์ฐ์ฐ์ Rollback(๋๋ Aborted) ๋ผ ๋ถ๋ฅธ๋ค.
Consistency(์ ํฉ์ฑ) - ํธ๋์ญ์ ์ ์ธ์ ๋ ๊ฐ์ ์ ๋ ฅ์๋ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์์ผํ๋ค.
- ์์คํ
์ด ๊ฐ์ง๊ณ ์๋ ๊ณ ์ ์์(์ ์ฝ์กฐ๊ฑด)๋ค์ ํธ๋์ญ์
์ํ ์ ๊ณผ ํธ๋์ญ์
์ํ ์๋ฃ ํ์ ์ํ๊ฐ ๊ฐ์์ผ ํ๋ค.
Isolation(๋ ๋ฆฝ์ฑ,๊ฒฉ๋ฆฌ์ฑ) - ๊ฐ๊ฐ์ ํธ๋์ญ์ ์ ๋ ๋ฆฝ์ ์ด๋ค. ์คํ ์ค ์๋ก ์ํฅ๋ผ์น์ง ์๋๋ค.
- ๋ ์ด์์ ํธ๋์ญ์ ์ด ๋์์ ๋ณํ ์คํ๋๋ ๊ฒฝ์ฐ ์ด๋ ํ๋์ ํธ๋์ญ์ ์คํ์ค์ ๋ค๋ฅธ ํธ๋์ญ์ ์ ์ฐ์ฐ์ด ๋ผ์ด๋ค ์ ์๋ค.
- ์ํ์ค์ธ ํธ๋์ญ์
์ ์์ ํ ์๋ฃ๋ ๋๊น์ง ๋ค๋ฅธ ํธ๋์ญ์
์์ ์ํ ๊ฒฐ๊ณผ๋ฅผ ์ฐธ์กฐํ ์ ์๋ค.
Durablility(์์์ฑ,์ง์์ฑ) - ํธ๋์ญ์ ์ ์ํด ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ๋ ์๊ตฌ์ ์ผ๋ก ์ ์ฅ๋๋ค.
- ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋ ํธ๋์ญ์ ์ ๊ฒฐ๊ณผ๋ ์์คํ ์ด ๊ณ ์ฅ๋๋๋ผ๋ ์๊ตฌ์ ์ผ๋ก ๋ฐ์๋์ด์ผ ํ๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ผ์ด๋๋ ๋ชจ๋ ์์ ์ ํธ๋์ญ์ ์ด ๊ฑธ๋ฆฐ๋ค.
ํ์ง๋ง ๋ชจ๋ ์์ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋จ์์ ์๋ฒฝํ ACID ํ๊ฒ ์ฒ๋ฆฌํ๋ ค๋ฉด, ํ ์ด๋ธ ์ ๊ธ์ด ๋๋ฌด ๋ง์ด ๊ฑธ๋ ค ์ฑ๋ฅ์ด ์์ข์์ง๋ค.
๊ทธ๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํธ๋์ญ์ ๊ฒฉ๋ฆฌ๋ ๋ฒจ์ด ์กด์ฌํ๋ค.
๐ฏ ํธ๋์ญ์ ๊ฒฉ๋ฆฌ๋ ๋ฒจ?
ํธ๋์ญ์ ์์ ์ผ๊ด์ฑ์ด ์๋ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ๋ ์์ค. ๊ตฌ์ฒด์ ์ผ๋ก ๋งํ์๋ฉด ๋์์ ์ฌ๋ฌ ํธ๋์ญ์ ์ด ์ฒ๋ฆฌ ๋ ๋, A ํธ๋์ญ์ ์ด Bํธ๋์ญ์ ์์ [๋ณ๊ฒฝ&์กฐํํ๋ ๋ฐ์ดํฐ]๋ฅผ ์ฝ์ ์ ์๋๋ก ํ์ฉํ ์ง ๋ง์ง๋ฅผ ๊ฒฐ์ ํ๋ ์์ค์ ์๋ฏธํ๋ค.
- READ UNCOMMITTED (์ปค๋ฐ ๋ฌด์ํ๊ณ ์ค๊ฐ์ ๋ง ์ฝ๊ธฐ)
- READ COMMITTED (์ปค๋ฐ๋ ๋ฐ์ดํฐ๋ง ์ฝ๊ธฐ)
- REPEATABLE READ (ํ ํธ๋์ญ์ ์์ ์ฌ๋ฌ๋ฒ ์ฝ์ด๋ ๋์ผํจ ๋ณด์ฅ)
- SERIALIZABLE (์์๋๋ก ์คํ, ์์ ๋ง๋ค ์ ๋ถ ๋ค ๋ฐ์ดํฐ ์ ๊ธ)
ํธ๋์ญ์
์ ์์์ ์ด๋ฉด์ ๋
๋ฆฝ์ ์ธ ์ํ์ ํด์ผํ๋ค.(ACID) ๊ทธ๋์ ํธ๋์ญ์
์ด DB๋ฅผ ๋ค๋ฃจ๋ ๋์, ๋ค๋ฅธ ํธ๋์ญ์
์ด ๊ด์ฌ ๋ชปํ๊ฒ Locking์ ํด์ผํ๋๋ฐ, ๋ฌด์์ ๋ค ์ ๊ทธ๊ฒ๋๋ฉด DB์ ์ฑ๋ฅ์ด ํฌ๊ฒ ๋จ์ด์ง๋ค. ์ด๋๊น์ง ์ ๊ธ ๊ฒ์ธ๊ฐ ์ ํ๋ ๊ฒ์ด ํธ๋์ญ์
์ ๊ฒฉ๋ฆฌ์์ค์ด๋ค.
๐ฏ (Lock) ์ ๊ทผ๋ค๋ ๊ฒ์?
์ฌ์ฉ์ค์ธ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฑฐ๋ ์กฐ์ํ์ง ๋ชปํ๊ฒ ๋ง๋๋ค๋ ๊ฒ์ด๋ค.
- ํ ํ ์ด๋ธ ์ ์ฒด๋ฅผ ์ ๊ธ ์ ์๋ค.
- ํ
์ด๋ธ์ ํ ํ(row)๋ฅผ ์ ๊ธ ์ ์๋ค.
- Shared Lock : ์ฝ๊ธฐ์ฉ ์ ๊ธ, ์ฝ๋ ๊ฑด ๊ฐ๋ฅํ์ง๋ง ๋ฐ์ดํฐ๋ฅผ ์์ ํ์ง ๋ชปํ๊ฒ ๋ง๋๋ค.
- Exclusive Lock : ์ํธ๋ฒ ํ์ ์ธ ์ ๊ธ, ์ฝ๊ณ ์ฐ์ง ๋ชปํ๊ฒ ์์ ํ ๋ง๋๋ค.
์ํธ๋ฒ ํ์ ์ด๋ผ๋๊ฑด, ๋ ์ค ํ๋๋ง ์ฌ์ฉ ๊ฐ๋ฅํ๋ค๋ ๋ง์ด๋ค. - ๊ทธ ์ธ, ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ง๋ค ์ฑ๋ฅ ํฅ์์ ์ํ ๋ค์ํ ํํ์ ์ ๊ธ์ด ์กด์ฌํ ์ ์๋ค.
๐ฏ ์๋ฐ์์ DB๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์?
JDBC๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ง ์กด์ฌํ๋ค. (* ๋ฌผ๋ก ์ ์์ค์ TCP/IP ๋คํธ์ํฌ ํต์ ์ ์ง์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ๋ ์์ง๋ง, ์ด๋ ์ ์ธํ๊ณ )
// ์ฐธ๊ณ ๋ก Java7 ์ดํ์์๋ ์ง์ close ํ์ง์์๋, try(..)๋ฅผ ์ฌ์ฉํด AutoClosable์ ์ด์ฉํ ์ ์๋ค.
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
sql = "SELECT * FROM MEMBER"
// 1. ๋๋ผ์ด๋ฒ ์ฐ๊ฒฐ DB ์ปค๋ฅ์
๊ฐ์ฒด๋ฅผ ์ป์
connection = DriverManager.getConnection(DBURL, DBUSER, DBPASSWORD);
// 2. ์ฟผ๋ฆฌ ์ํ์ ์ํ Statement ๊ฐ์ฒด ์์ฑ
stmt = conn.createStatement();
// 3. executeQuery: ์ฟผ๋ฆฌ ์คํ ํ
// ResultSet: DB ๋ ์ฝ๋ ResultSet์ ๊ฐ์ฒด์ ๋ด๊น
rs = stmt.executeQuery(sql);
} catch (Exception e) {
} finally {
conn.close();
pstmt.close();
rs.close();
}
}
๐ฏ ์๋ฐ์์ ์ด๋ป๊ฒ ํธ๋์ญ์ ์ด ๊ฑธ๋ฆฌ๋๊ฐ?
๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ํธ๋์ญ์ ๋จ์๋ก ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๋ค. Commit ๋์ง ์์๋๋ฐ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค๋ฉด, ํธ๋์ญ์ ์์ ์ ํต์ผ๋ก ๋กค๋ฐฑ์ํจ๋ค.
์๋ฐ์์๋ JDBC์ ์ฐ๊ฒฐ๋ Connection์ ์ด์ฉํ์ฌ ํธ๋์ญ์ ์ ๊ด๋ฆฌํ ์ ์๋ค.
// ์ปค๋ฅ์
ํ์์ DB์ปค๋ฅ์
์ ๋ฐ์์๋ค๊ณ ๊ฐ์
Connection connection = dataSource.getConnection();
try (connection) {
connection.setAutoCommit(false); // ์๋ ์ปค๋ฐ off
// ...DB ์์
...
connection.commit(); // ์ฑ๊ณต์ ํธ๋์ญ์
์ปค๋ฐ
} catch (SQLException e) {
connection.rollback(); // ์ค๋ฅ ๋ฐ์์ ํธ๋์ญ์
๋กค๋ฐฑ
}
๊ธฐ๋ณธ์ ์ผ๋ก ํธ๋์ญ์
์๋ ์ปค๋ฐ ๋ชจ๋์ธ๋ฐ, ์ด ๊ฒฝ์ฐ ๋ชจ๋ SQL๋ฌธ์ ๊ฐ๋ณ ํธ๋์ญ์
์ผ๋ก ์คํ๋๊ณ , ์ปค๋ฐ๋๋ค.
์ฐธ๊ณ ๋ก ๋๋ถ๋ถ์ ์ปค๋ฅ์
ํ์ JDBC์ AutoCommit์ ๋๊ณ ์ง์ ํธ๋์ญ์
์ ๊ด๋ฆฌํ๋ค.
- Insert, Update, Delete ์์ ์ ์คํ์ด ์๋ฃ ๋๋ ์ฆ์ Commit ๋๋ค.
- Select ์์ ์ ์ฐ๊ฒฐ๋ ๊ฒฐ๊ณผ๊ฐ์ฒด(ResultSet)์ด ๋ซํ๋ฉด Commit ๋๋ค.
- connection.setReadOnly(true) ์ ์ฉํ ๊ฒฝ์ฐ, DB ๋๋ผ์ด๋ฒ์ ํํธ๋ฅผ ์ ๊ณตํ๋ค. ๋จ ํธ๋์ญ์ ์คํ ๋์ค์๋ ์ค์ ์ ๋ณ๊ฒฝํ ์ ์๋ค.
์๋ ์ปค๋ฐ๋ชจ๋๊ฐ ์๋ ๊ฒฝ์ฐ, Commit ํ๊ฑฐ๋ Rollback ํ ๋ ์์ ์ด ์ข ๋ฃ๋๋ค.
์ค๋ผํด ๊ณต์๋ฌธ์ - setAutoCommit (Java17)
์ฐธ๊ณ ๋ก Spring์ ํ์ด๋ฒ๋ค์ดํธ์์ ์ ๊ณตํด์ฃผ๋ @Transactional๋ ์์์ ํธ๋์ญ์ ์ ๊ด๋ฆฌํด์ฃผ๋ ๋ง๋ฒ์ ํค์๋๊ฐ ์๋๋ค. ์ถ์ํํด์ ์ฌ์ฉํ ๋ฟ์ด์ง ์ค์ ๋ ์์ ์ฝ๋์ฒ๋ผ JDBC ํธ๋์ญ์ ์ ์ฌ์ฉํ์ฌ ๊ตฌํํ๋ค.
๐ฏ ์ฌ๋ฌ Select๋ฅผ ํ๋์ ํธ๋์ญ์ ์ผ๋ก ๋ฌถ์ผ๋ฉด ์ด๋ป๊ฒ ๋๋๊ฐ?
DB์ ๋์์ฑ ์ ์ด ๋ฉ์ปค๋์ฆ์ ๋ฐ๋ผ ๋ค๋ฅด๋ค. ๋ค๋ง ๋๋ถ๋ถ์ ๊ฒฝ์ฐ READ-COMMIT ๊ฒฉ๋ฆฌ ์์ค์์ ๋ฌถ๋ ๊ฒฝ์ฐ์๋ ์ด์ ์ ๋ฐ๋ก ์๋ค.
๋น์ฐํ REPEATABLE-READ ์ ๊ฒฝ์ฐ, ๋ฌถ๋ ๊ฒฝ์ฐ์ ๋ฌถ์ง ์๋ ๊ฒฝ์ฐ ๋ฐ์ดํฐ ๊ฒฐ๊ณผ๊ฐ ๋ค๋ฅผ ์ ์๋ค
๋ฐ๋๋ก ๋๋ฌด ๋ง์ด ๋ฌถ์ด ํด๋น ํธ๋์ญ์ ์ด ์ฅ๊ธฐ ์คํ ๋ ๊ฒฝ์ฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฑ๋ฅ์ด ์ ์ข์ ์ง ์ ์๋ค.
ํธ๋์ญ์ ์ด ์ข ๋ฃ ๋ ๋ ๊น์ง ํ ์ด๋ธ์ ์ผ๋ถ๋ฅผ ์ ๋ฐ์ดํธ ํ ์ ์๊ธฐ๋๋ฌธ์ด๋ค. (์ด๋ Select๊ฐ ์๋ DDL, Index ๋ณ๊ฒฝ์์ ๋ ๋ง์ฐฌ๊ฐ์ง)
* ๋จ, ์๋ฒ(Java)์ ์ฅ์์๋ Select๋ฅผ ์๋ํ ๋๋ง๋ค DB Connection์ ์๋กญ๊ฒ ์์ฑํ๋ค๋ฉด ์๋ฒ ์ฑ๋ฅ์ด ๋๋น ์ง๊ฒ ์ง๋ง, ์ด๋ ์ปค๋ฅ์ ํ์ ์ฌ์ฉํ๋ฉด ํด๊ฒฐ๋๋ค.
๐ฏ ์ปค๋ฅ์ ์ ๋ฏธ๋ฆฌ ์ด์ด๋๋ค๋ ๊ฒ ์ ํํ ๋ฌด์จ ์๋ฏธ์ธ๊ฐ?
Java ์๋ฒ๋ JVM ์์์ ๋์๊ฐ๋ ํ๋ก๊ทธ๋จ์ด๊ณ , JVM์ ์ด์์ฒด์ ์์์ ๋์๊ฐ๋ ํ๋ก๊ทธ๋จ, ์ ํํ๋ ํ๋ก์ธ์ค์ด๋ค.
์๋ฒ(ํ๋ก์ธ์ค)๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค(ํ๋ก์ธ์ค)์ ์ฐ๊ฒฐํ๊ธฐ ์ํด์๋ TCP/IP๊ฐ ๊ตฌํ๋ ์ด์์ฒด์ ๊ฐ ์ ๊ณตํด์ฃผ๋ ์์ผ ํต์ ์ ํด์ผํ๋ค.
์์ผ์ 1982๋ BSD(Berkeley Software Distribution) ์ ๋์ค 4.1์์ ์ฒ์ ์๊ฐ๋์์ผ๋ฉฐ ํ์ฌ ์ฌ์ฉ์ค์ธ ์์ผ์ ์ ํํ 1986๋ BSD ์ ๋์ค4.3์์ ๊ฐ์ ๋ ๊ธฐ๋ฅ์ด๋ค. ์ดํ TCP/IP ์ ํ์ค์ผ๋ก ์ฑํ๋์๋ค.
์ด์์ฒด์ ๊ฐ ์ ๊ณตํ๋ Socket ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ๊ธฐ ์ํด์ , System Call ๋ช ๋ น์ ์ด์ฉํ์ฌ ์ปค๋ ๋ชจ๋๋ก ์ง์ ํด์ผํ๋ค.
์ด์
๋ธ๋ฆฌ(๊ธฐ๊ณ์ด) ์์๋ ํ์ํ ๋งค๊ฐ๋ณ์๋ฅผ (๋ ์ง์คํฐ ์์ฒด or ๋ ์ง์คํฐ์ ํน์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ ๊ธฐ๋ก or ์คํ ๋ฉ๋ชจ๋ฆฌ)์ ๋ฃ์ ํ
์ธํฐ๋ฝํธ ๋ช
๋ น(INT), ์์คํ
์ ๊ทผ ๋ช
๋ น(SYSENTER), ๋๋ x64 ์ดํ ์ด์์ฒด์ ๋ผ๋ฉด SYSCALL ๋ช
๋ น์ ์ด์ฉํ์ฌ ์์คํ
์ฝ์ ํ ์ ์๋ค.
C์ธ์ด์์๋ ํ์ผ๋์คํฌ๋ฆฝํฐ๋ฅผ ์ฌ์ฉํ๋ API๋ฅผ ์ด์ฉํ์ฌ ์์คํ
์ฝ์ ํ ์ ์๊ณ , ๊ทธ ๊ณผ์ ์ ์๋์ ๊ฐ๋ค.
C ํ๋ก์ธ์ค -> ์์คํ
์ฝ -> ์ปค๋ -> ๋์คํฌ ์ปจํธ๋กค๋ฌ -> ๋ฐ์ดํฐ ๋ณต์ฌ
์๋ฐ์์๋ ํฌ๊ฒ ๋ค๋ฅด์ง์๋ค. ์๋์ ๊ณผ์ ์ผ๋ก ์์คํ
์ฝ์ด ์ด๋ฃจ์ด์ง๋ค.
JVM -> JNI -> ์์คํ
์ฝ -> ์ปค๋ -> ๋์คํฌ ์ปจํธ๋กค๋ฌ -> ์ปค๋ ๋ฒํผ ๋ณต์ฌ -> JVM ๋ฒํผ ๋ณต์ฌ
์ฐธ๊ณ ๋ก ํ์ผ ์ ์ถ๋ ฅ์ด๋ ๋คํธ์ํฌ ์ ์ถ๋ ฅ์ด๋ ์ด์์ฒด์ ์ ์ฅ์์๋ ๋์์ด ํฌ๊ฒ ๋ค๋ฅด์ง ์๋ค. I/O ๋ณ๋ชฉ๋๋ ๊ฒ๋ ๋น์ทํ๊ณ .
์๋ฐ์์๋ ์ด๋ฌํ ์์ผ ํต์ ์ java.net.Socket, java.net.ServerSocket ์ ์ด์ฉํ์ฌ ์ง์ ํ ์ ์๋ค.
baeldung.com - ์๋ฐ ์์ผ ํต์ ๊ฐ์ด๋
// ์๋ฒ ์์ผ์์ฑ ํ, ์์ผ์ ์ด์ฉํ ์๋ฐ IO ์คํธ๋ฆผ ์์ฑ
Socket clientSocket = new Socket("127.0.0.1", 6666);
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
// (๋ค๋ฅธ ํ๋ก๊ทธ๋จ) ํด๋ผ์ด์ธํธ ์์ผ ์์ฑ ํ, ์์ผ์ ์ด์ฉํ ์๋ฐ IO ์คํธ๋ฆผ ์์ฑ
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
์ด๊ฑธ๋ก ์ง์ ํต์ ์ ํด๋ ๋์ง๋ง, ๋คํํ java.sql ํจํค์ง์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ผ ํต์ ์ ์ฝ๊ฒ ํ ์ ์๊ฒ Connection ๊ฐ์ฒด๋ฅผ ์ ๊ณตํ๋ค.
์๋ฐ์์ .getConnection(..) ์ ์ปค๋ฅ์ ๊ฐ์ฒด ๊ตฌํ์ ํด๋น JDBC ๋๋ผ์ด๋ฒ๊ฐ ๊ตฌํํ๋๋ก ๋ง๋ค์ด๋จ๋ค.
// DataSource ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด์ธ JdbcRowSetImpl ์ ์ฝ๋
private static Connection getConnection(
String url, java.util.Properties info, Class<?> caller) throws SQLException {
/* ... ์๋ต ... */
for (DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then skip it.
if (isDriverAllowed(aDriver.driver, callerCL)) {
try {
println(" trying " + aDriver.driver.getClass().getName());
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null)
reason = ex;
}
} else
println(" skipping: " + aDriver.driver.getClass().getName());
}
์ฆ ์ปค๋ฅ์ ์ ์ด์ด๋๋ค๋ ๊ฑด, ๋ฐ์ดํฐ๋ฒ ์ด์ค ํต์ ์ ์ํ ์์ผ์ ์ด์ด๋๋ค๋ ์๋ฏธ๋ค.
๐ฏ ์ปค๋ฅ์ ์ ๋ค๋ค์ต์ ์ธ๊ฐ?
- DB ์๋ฒ ์ ์์ ์ํด JDBC ๋๋ผ์ด๋ฒ๋ฅผ ๋ก๋ํ๋ค.
- DB ์ ์ ์ ๋ณด์ DriverManager.getConnection() Method๋ฅผ ํตํด DB Connection ๊ฐ์ฒด๋ฅผ ์ป๋๋ค.
- Connection ๊ฐ์ฒด๋ก ๋ถํฐ ์ฟผ๋ฆฌ๋ฅผ ์ํํ๊ธฐ ์ํ PreparedStatement ๊ฐ์ฒด๋ฅผ ๋ฐ๋๋ค.
- executeQuery๋ฅผ ์ํํ์ฌ ๊ทธ ๊ฒฐ๊ณผ๋ก ResultSet ๊ฐ์ฒด๋ฅผ ๋ฐ์์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ค.
- ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋๋ฉด ์ฒ๋ฆฌ์ ์ฌ์ฉ๋ ๋ฆฌ์์ค๋ค์ closeํ์ฌ ๋ฐํํ๋ค.
์ฌ๊ธฐ์์ ๊ฐ์ฅ ์๊ฐ์ด ์ค๋๊ฑธ๋ฆฌ๋ ๋ถ๋ถ์, DB์๋ฒ์ ์ต์ด๋ก ์์ผ ํต์ ์ ์ฐ๊ฒฐ Connection ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ถ๋ถ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด ๋ฌด์์ ์ปค๋ฅ์ ํ์ ํฌ๊ธฐ๋ฅผ ๋๋ฆฐ๋ค๋ฉด ์ข์๊น? ์๋. ๊ทธ๋ ์ง์๋ค.
๊ฒฐ๊ตญ ์ปค๋ฅ์
์ ์ฌ์ฉํ๋๊ฑด ์๋ฒ์ ๋์๊ฐ๊ณ ์๋ Thead์ด๋ค.
Thread์ ๊ฐ์๋ณด๋ค ์ปค๋ฅ์
ํ์ ํฌ๊ธฐ๊ฐ ํฌ๋ค๋ฉด ์ฌ์ฉํ์ง๋ ์๋ ์ฌ์ ์ปค๋ฅ์
๋ง ๋ง์ด ์๊ฒจ ๋ฉ๋ชจ๋ฆฌ์ ๋ญ๋น ํ๊ณ ์์ ๋ฟ์ด๋ค.
MySQL8.0 ๊ณต์๋ ํผ๋ฐ์ค์์๋ 600์ฌ ๋ช
์ ์ ์ ๋ฅผ ๋์ํ๋๋ฐ 15~20๊ฐ์ ์ปค๋ฅ์
ํ๋ง์ผ๋ก๋ ์ถฉ๋ถํ๋ค๊ณ ์ธ๊ธํ๊ณ ์๋ค. MySQL์ ์ต๋ ์ฐ๊ฒฐ ์๋ฅผ ๋ฌด์ ํ์ผ๋ก ์ค์ ํ ๋ค ๋ถํ ํ
์คํธ๋ฅผ ์งํํ๋ฉด์ ์ต์ ํ๋ ๊ฐ์ ์ฐพ๋ ๊ฒ์ ์ถ์ฒํ๋ค.
์ฌ์ค ์ด๋ฐ ๊ฑด ์๋ฒ๋ง๋ค ์ต์ ์ ๊ฐ์ด ๋ค๋ฅด๊ธดํ๋ค. ๊ถ๊ธํ๋ค๋ฉด ๋ฐฐ๋ฌ์๋ฏผ์กฑ - HikariCP Dead lock์์ ๋ฒ์ด๋๊ธฐ (์ค์ ํธ) ๊ธ์ ์ฝ์ด๋ณด์.
๐ฏ ์คํ๋ง ๋ฐ์ดํฐ JPA์์, ์ฌ๋ฌ SELECT ๋ฌธ์ ํ๋๋ก ๋ฌถ๋ ๊ฑด ์ด๋ค ์ฐจ์ด๊ฐ ์์๊น
@Transcational
void serviceMethod(){
memberRepository.read()
shopRepository.read()
orderRepository.read()
}
@Transcational ํค์๋๋ ํด๋น ๋ฉ์๋์ ์์, ๋์ PlatformTranscationManager๋ฅผ ํ๋ก์๋ก ์ฝ์
ํ๋ค.
๊ทธ๋ฆฌ๊ณ .begin() .doCommit() ๊ฐ์ ๋ฉ์๋๋ฅผ ์คํ์์ผ ํธ๋์ญ์
์ ๊ฑธ์ด์ค๋ค.
JPA์ ๊ฒฝ์ฐ์๋ JpaTransactionManager ๊ฐ ๊ตฌํ์ฒด๋ก ์ฝ์ ๋๋๋ฐ, ์ฝ๋๋ฅผ ๋ณด๋ฉด ์๊ฒ ์ง๋ง .doCommit()์ ํธ๋์ญ์ ์ ์ปค๋ฐํ๋ค.
์ฐธ๊ณ ๋ก ์ฐ๋ฆฌ๊ฐ ๋ฐ๋ก ํธ๋์ญ์ ์ ๊ฑธ์ง ์์๋ ๊ธฐ๋ณธ ๊ตฌํ์ฒด์ธ SimpleJpaRepository์์ ํธ๋์ญ์ ์ด ๊ฑธ๋ ค์๋ค.
@Transcational
void serviceMethod(){
memberRepository.read()
shopRepository.read()
orderRepository.read()
}
๋ค์ ๋ณธ๋ก ์ผ๋ก ๋์์์, ์๋์ ๊ฐ์ด ์กฐํ๋ฉ์๋์ @Transactional์ ๊ฑธ๊ฒ๋๋ฉด
- ๊ทธ๋ฅ ์ฌ๋ฌ Select ๋ค์ ํ ํธ๋์ญ์
์ ๋ฃ์ด๋ฒ๋ฆฐ๋ค.
- JPA๊ฐ ๋ํฐ์ฒดํน(์์ ๊ฐ์ง)๋ฅผ ํ๋ค.
DB์ ๋์์ฑ ์ ์ด ๋ฉ์ปค๋์ฆ์ ๋ฐ๋ผ ๋ค๋ฅด๋ค. ๋ค๋ง ๋๋ถ๋ถ์ ๊ฒฝ์ฐ READ-COMMIT ๊ฒฉ๋ฆฌ ์์ค์์ ๋ฌถ๋ ๊ฒฝ์ฐ์๋ ์ด์ ์ ๋ฐ๋ก ์๋ค.๋น์ฐํ REPEATABLE-READ ์ ๊ฒฝ์ฐ, ๋ฌถ๋ ๊ฒฝ์ฐ์ ๋ฌถ์ง ์๋ ๊ฒฝ์ฐ ๋ฐ์ดํฐ ๊ฒฐ๊ณผ๊ฐ ๋ค๋ฅผ ์ ์๋ค
๋ฐ๋๋ก ๋๋ฌด ๋ง์ด ๋ฌถ์ด ํด๋น ํธ๋์ญ์ ์ด ์ฅ๊ธฐ ์คํ ๋ ๊ฒฝ์ฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฑ๋ฅ์ด ์ ์ข์ ์ง ์ ์๋ค.
ํธ๋์ญ์ ์ด ์ข ๋ฃ ๋ ๋ ๊น์ง ํ ์ด๋ธ์ ์ผ๋ถ๋ฅผ ์ ๋ฐ์ดํธ ํ ์ ์๊ธฐ๋๋ฌธ์ด๋ค. (์ด๋ Select๊ฐ ์๋ DDL, Index ๋ณ๊ฒฝ์์ ๋ ๋ง์ฐฌ๊ฐ์ง)
* ๋จ, ์๋ฒ(Java)์ ์ฅ์์๋ Select๋ฅผ ์๋ํ ๋๋ง๋ค DB Connection์ ์๋กญ๊ฒ ์์ฑํ๋ค๋ฉด ์๋ฒ ์ฑ๋ฅ์ด ๋๋น ์ง๊ฒ ์ง๋ง, ์ด๋ ์ปค๋ฅ์ ํ์ ์ฌ์ฉํ๋ฉด ํด๊ฒฐ๋๋ค.
๊ทธ๋ผ ์๋์ ๊ฐ์ด readOnly=true๋ก ๋ฌถ์ด์ฃผ๋ฉด ์๋ฏธ์๋ ์ฐจ์ด๊ฐ ์์๊น?
@Transcational(readOnly=true)
void serviceMethod(){
memberRepository.read()
shopRepository.read()
orderRepository.read()
}
์ฐ์ JDBC ์์๋ readOnly ์ ๋ํ ์ต์ ํ๋ JDBC Driver์๊ฒ ์์ํ ๋ฟ, ์๋ฌด๋ฐ ๋์๋ ํ์ง ์๋๋ค.
์ฐธ๊ณ ๋ก readOnly๋ผ๊ณ ํด์ ์์ฑ,์ญ์ ,์ ๋ฐ์ดํธ๋ฅผ ๋ง์์ฃผ๋ ๊ธฐ๋ฅ์ JDBC์์ ์๋ค. ๊ทธ๋ฅ readOnly ํํธ๋ง JDBC๋๋ผ์ด๋ฒ์๊ฒ ์ค๋ค.
ํ์ง๋ง JPA์ ๊ตฌํ์ฒด์ธ ํ์ด๋ฒ๋ค์ดํธ์์๋ ๋ช๊ฐ์ง ์ต์ ํ๋ฅผ ํ๋ค.
# (๋ฒ์ธ) @Transcational(readOnly = true)์ ๋์
- ๋ฉ๋ชจ๋ฆฌ์ ์กด์ฌํ๋ ์์์ฑ ์ปจํ ์คํธ๋ฅผ ํ๋ฌ์ ํ์ง ์๋๋ค. entityManager.setFlushMode(MANUAL) ๋ก ๊ฐ์ ๋ก ๋ฐ๊ฟ๋ฒ๋ฆฐ๋ค.
- ์ข ๋ ์ฝ๊ฒ๋งํ๋ฉด ๋ํฐ์ฒดํน์ ์ํ๋ค.
- ๊ทธ ์ธ ์ฐจ์ด์ ์, ์ฐ๊ด๊ด๊ณ๊ฐ LAZY๋ก ๊ฑธ๋ ค์๋ค๋ฉด ํด๋น ํธ๋์ญ์ ๋ด๋ถ์์๋ ์ง์ฐ๋ก๋ฉ์ ํ๋ค๋๊ฑฐ ์ ๋๊ฐ ์๊ฒ ๋ค.
* ์ฐธ๊ณ ๋ก ๋ํฐ์ฒดํน๊ณผ flush๋ฅผ ์ํ๋ค๊ณ ํ์ง, ํธ๋์ญ์
์ readOnly๊ฐ ์์ /์ญ์ ๋ฅผ ๋ง๋ ๊ธฐ๋ฅ์ด ์์ง๋ ์๋ค.
save()๋ฅผ ์คํํด๋ ์ ๋์ํ๊ณ , updated์ ๊ฒฝ์ฐ์๋ ์ง์ flush ์์ผ์ฃผ๋ฉด ์ค์ DB์ ์ฟผ๋ฆฌ๊ฐ ์ฐํ๋ค.
์ฆ ์์ฝํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ฒฉ๋ฆฌ ์์ค์ด Read Commit ์ธ ๊ฒฝ์ฐ ์๋ฌด๋ฐ ์ฐจ์ด๊ฐ ์๋ค.
๊ตณ์ด ๋ฐ์ง์๋ฉด ํ ํธ๋์ญ์
์ด ๊ธธ์ด์ง = ์ฌ๋ฌ ๋ฐ์ดํฐ์ SharedLock์ด ๊ฑธ๋ ค์ ์ฑ๋ฅ์ด ๋๋ ค์ง ์ ์๋ค.
Repeatable read ์ ๊ฒฝ์ฐ, ํธ๋์ญ์ ์ ๊ฑด ๊ฒ๊ณผ ์๊ฑด ๊ฒ์ด ๋ฐ์ดํฐ ์ ๊ธ ๋ฒ์์ ๋ฐํ๊ฐ์ด ๋ค๋ฅผ ์ ์๊ธฐ์ ์ด๋ ๋ ผ์ธ๋ก ํ์.
'๐๊ธฐ๋ณธ ์ง์ > Java ๊ธฐ๋ณธ์ง์' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ฃผ๊ด์ ์ธ ์ธํ๋ฐ ๊ฐ์ ๋ฆฌ๋ทฐ(๐ฑ๊น์ํ๋ ์คํ๋ง) (18) | 2024.02.15 |
---|---|
Java ์์ ์๊ฐ์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ (Instant.now(), LocalDate.now()) (1) | 2023.01.28 |
์๋ฐ์ NIO (java.nio) (1) | 2022.03.08 |
์๋ฐ์ ๋์์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋์๊ตฌ์กฐ (Atomic, Adder, Accumulator) (0) | 2022.03.08 |
์ค๋ธ์ ํธ ๋์์ธ ์คํ์ผ #1 ๊ฐ์ฒด์งํฅ, ์๋น์ค ์์ฑํ๊ธฐ (0) | 2021.10.04 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev