ํธ๋์ญ์ ๊ฐ ๋ ๋ฆฝ์ฑ ๋ณด์ฅ
ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค (Isolation Level)
ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ๋ ๋ฒจ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋์์ ์คํ๋๋ ํธ๋์ญ์ ๊ฐ์ ๊ฐ์ญ์ ๊ด๋ฆฌํ๊ธฐ ์ํ ๊ธฐ์ค์ด๋ค. ACID ์์น ์ค "์ผ๊ด์ฑ(Consistency)"๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํ ํต์ฌ ์์์ด๋ค.
1๏ธโฃ ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค์ด๋ ?
ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค์ ์ฌ๋ฌ ํธ๋์ญ์ ์ด ๋์์ ์คํ๋ ๋, ํน์ ํธ๋์ญ์ ์ด ๋ค๋ฅธ ํธ๋์ญ์ ์ ๋ฐ์ดํฐ๋ฅผ ๋ณผ ์ ์๋ ์ ๋๋ฅผ ๊ฒฐ์ ํ๋ ์ค์ ์ด๋ค.
๊ฒฉ๋ฆฌ ์์ค์ ์๋์ ๊ฐ์ด ๋ฎ์ ์์ค(Low Isolation) ์์ ๋์ ์์ค(High Isolation)์ผ๋ก ๋๋๋ค.
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
๊ฒฉ๋ฆฌ ์์ค์ด ๋์์ง์๋ก ๋ฐ์ดํฐ ์ ํฉ์ฑ(Data Integrity)์ด ๊ฐํ๊ฒ ๋ณด์ฅ๋์ง๋ง, ๋์์ ์ฑ๋ฅ ์ ํ๊ฐ ๋ฐ์ํ ์ ์๋ค.
2๏ธโฃ ๊ฒฉ๋ฆฌ ์์ค ๋ณ ๋์๊ณผ ํน์ง
๊ฒฉ๋ฆฌ ์์ค | Dirty Read | Non-Repeatable Read | Phantom Read | ๋์์ฑ |
READ UNCOMMITTED | ๋ฐ์ | ๋ฐ์ | ๋ฐ์ | ๐ฅ ์ต๊ณ |
READ COMMITTED | ๋ฐฉ์ง | ๋ฐ์ | ๋ฐ์ | ๐ ๋์ |
REPEATABLE READ | ๋ฐฉ์ง | ๋ฐฉ์ง | ๋ฐ์(MySQL ๊ฑฐ์ ์์) | ๐ ๋ณดํต |
SERIALIZABLE | ๋ฐฉ์ง | ๋ฐฉ์ง | ๋ฐฉ์ง | ๐ ๋ฎ์ |
3๏ธโฃ ๊ฒฉ๋ฆฌ ์์ค ์์ธ ์ค๋ช
1. READ UNCOMITTED (L0)
- ํน์ง : ์ปค๋ฐ๋์ง ์์ ๋ฐ์ดํฐ๋ ์ฝ์ ์ ์๋ ๊ฐ์ฅ ๋ฎ์ ์์ค์ ๊ฒฉ๋ฆฌ. (ROLLBACK, COMMIT ์ฌ๋ถ์ ์๊ด์์ด ๋ชจ๋ ๊ฐ์ ์ฝ๋๋ค.)
- ์ฅ์ : ์ฑ๋ฅ์ด ๊ฐ์ฅ ๋ฐ์ด๋จ. (๋ฐ์ดํฐ ์ผ๊ด์ฑ ํน์ ์ ํฉ์ฑ์ด ์กฐ๊ธ ๋จ์ด์ง๋๋ผ๋ ์ฑ๋ฅ์ ๊ทน๋ํํ ๋ ์ฌ์ฉํ๋ค.)
- ๋จ์ : Dirty Read, Non-Repeatable Read, Phantom Read ๋ชจ๋ ๋ฐ์ ๊ฐ๋ฅ.
- ์ ์ฉ์ฌ๋ก : "์ฝ๊ธฐ"๊ฐ ๋งค์ฐ ๋น๋ฒํ์ง๋ง ๋ฐ์ดํฐ ์ ํฉ์ฑ์ด ๋ง์ด ํ์ ์๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ ํฉํ๋ค. โ ๊ฑฐ์ ์ฌ์ฉํ์ง ์๋ ์์ค. (๋ฐ์ดํฐ ์ ํฉ์ฑ ๋ฌธ์ )
๐ก ์์: Dirty Read
- ํธ๋์ญ์ A: ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ์ง๋ง ์์ง ์ปค๋ฐํ์ง ์์.
- ํธ๋์ญ์ B: ํธ๋์ญ์ A์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์.
- ํธ๋์ญ์ A๊ฐ ROLLBACK ํ๋ฉด, ํธ๋์ญ์ B๋ ์๋ชป๋ ๋ฐ์ดํฐ๋ฅผ ์ฐธ์กฐํ๊ฒ ๋๋ค.

2. READ COMMITTED (L1)
- ํน์ง: ์ปค๋ฐ๋ ๋ฐ์ดํฐ๋ง ์ฝ์ ์ ์๋ค.
- ์ฅ์ : Dirty Read๋ ๋ฐฉ์ง๋๋ค.
- ๋จ์ : Non-Repeatable Read, Phantom Read ๋ฐ์ ๊ฐ๋ฅ.
- ์ ์ฉ ์ฌ๋ก: ์ค๋ผํด์ ๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ ์์ค์ผ๋ก, ๋ฐ์ดํฐ ์ ํฉ์ฑ๊ณผ ๋์์ฑ์ด ํ์ํ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค. โ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ๊ฒฉ๋ฆฌ ์์ค์ผ๋ก, ์ปค๋ฐ๋์ง ์์ ์ ๋ณด๋ ์ฝ์ ์ ์๋ค.
๐ก ์์: Non-Repeatable Read
- ํธ๋์ญ์ A: ๋ฐ์ดํฐ๋ฅผ ์ฝ์
- ํธ๋์ญ์ B: ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ๊ณ ์ปค๋ฐ.
- ํธ๋์ญ์ A๊ฐ ๋ค์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ผ๋ฉด ๊ฐ์ด ๋ณ๊ฒฝ๋๋ค.

๐ก MVCC์ READ COMMITTED
READ COMMITTED๋ถํฐ MVCC(Mulitiversion Concurrency Control, ๋ค์ค ๋ฒ์ ๋์์ฑ ์ ์ด) ๊ฐ ์ ์ฉ๋๋ค.
MVCC๋ ํธ๋์ญ์ ๋์์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํด ๋ฐ์ดํฐ์ ์ฌ๋ฌ ๋ฒ์ (Snapshots)์ ๊ด๋ฆฌํ๋ฉฐ, Lock ์์ด๋ ์ผ๊ด๋ ๋ฐ์ดํฐ ์ฝ๊ธฐ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ค.
MVCC ๋์ ์๋ฆฌ
- ๋ฐ์ดํฐ ๋ณ๊ฒฝ ์ Undo ์์ญ์ ์๋ณธ ๋ฐ์ดํฐ ๋ฐฑ์
:
- ๋ฐ์ดํฐ๋ ํ ์ด๋ธ์ ์ฆ์ ๋ฐ์๋์ง๋ง, ์ด์ ๋ฐ์ดํฐ๋ Undo ์์ญ์ ์ ์ฅ.
- ํธ๋์ญ์
์์ ์ Snapshot ์์ฑ:
- Snapshot์ Undo์์ญ์ ๊ธฐ๋ฐ์ผ๋ก ํธ๋์ญ์ ์ด ์ฝ์ ๋ฐ์ดํฐ๋ฅผ ๊ฒฐ์ ํ๋ค.
- Garbage Collection์ผ๋ก ๋ถํ์ํ Undo ๋ฐ์ดํฐ ์ญ์ :
- ํ์ ์์ด์ง Undo ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ธฐ์ ์ผ๋ก ์ ๋ฆฌํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํ๋ค.
MySQL(InnoDB)์์์ MVCC
- MySQL(InnoDB)์์๋ Undo ์์ญ์ ํ์ฉํ์ฌ MVCC๋ฅผ ์ง์ํ๋ค.
- ์ฃผ์ ๋์:
- Consistent Read(์ผ๊ด๋ ์ฝ๊ธฐ): ํธ๋์ญ์ ์ ํ ์ด๋ธ์ ์ค์ ๋ฐ์ดํฐ๊ฐ ์๋ Undo ์์ญ์ Snapshot ๋ฐ์ดํฐ๋ฅผ ์ฝ์.
- Dirty Read ๋ฐฉ์ง: ์ปค๋ฐ๋์ง ์์ ๋ฐ์ดํฐ๋ Undo์์ญ์ ํตํด ๋ฐฐ์ .
- ์ฃผ์: Undo ์์ญ์ด ๊ณผ๋ํ๊ฒ ์์ด๋ฉด Garbage Collection์ ๋ฐ๋ฅธ ์ฑ๋ฅ ์ ํ ๊ฐ๋ฅ.
PorstgreSQL์์์ MVCC
- PostgreSQL์ Snapshot Isolation ๋ฐฉ์์ ์ฌ์ฉํ์ฌ MVCC๋ฅผ ์ง์ํ๋ค.
- ์ฃผ์ ๋์:
- ๋ฐ์ดํฐ ๋ณ๊ฒฝ ์ ํธ๋์ญ์ ์์ ์์ ์ Snapshot์ ์ฐธ์กฐํ๋ค.
- First-Commiter Win : ๋์์ ๋์ผ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ค๋ ๊ฒฝ์ฐ, ๋จผ์ ์ปค๋ฐํ ํธ๋์ญ์ ๋ง ์ฑ๊ณตํ๋ค..
3. REPEATABLE READ (L2) (MySQL ๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ ์์ค)
- ํน์ง: ๋์ผ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณต ์ฝ์ ๋ ํญ์ ๊ฐ์ ๊ฐ ๋ฐํ (MVCC ์ฌ์ฉ)
- ์ฅ์ : Dirty Read์ Non-Repeatable Read ๋ฐฉ์ง.
- ๋จ์ : Phantom Read ๊ฐ๋ฅ (MySQL์์๋ ๊ฑฐ์ ๋ฐ์ํ์ง ์๋๋ค)
- ์ ์ฉ ์ฌ๋ก: ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ด ์ค์ํ ์ดํ๋ฆฌ์ผ์ด์ .
๐ก MySQL์ MVCC์ Phantom Read ๋ฐฉ์ง
- MySQL์ ๊ฐญ ๋ฝ(Gap Lock)๊ณผ ๋ฅ์คํธ ํค ๋ฝ(Next-Key Lock)์ ์ฌ์ฉํ์ฌ Phantom Read๋ฅผ ๋ฐฉ์งํ๋ค.
- ๊ทธ๋ฌ๋ ์ ๊ธ ์๋ SELECT๋ก ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ๊ฒฝ์ฐ์๋ Phantom Read๊ฐ ๋ฐ์ํ ์ ์๋ค.
๐ก REPEATABLE READ์ Phantom Read
REPEATABLE READ๋ ํธ๋์ญ์ ๋ด์ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณตํด์ ์ฝ์ ๋ ํญ์ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ T๋ณด์ฅํ๋ค.
๊ทธ๋ฌ๋ ์๋ก์ด ๋ ์ฝ๋๊ฐ ์ถ๊ฐ๋๊ฑฐ๋ ์ญ์ ๋๋ ๊ฒฝ์ฐ(UPDATE X), Phantom Read ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ์๋ค.

1. ํธ๋์ญ์ T1
- T1 ํธ๋์ญ์ ์ ๋ฐ์ดํฐ "0"๋ฅผ ์กฐํ ํ ์์ (+A, -A) ์์ ์ ์ํํ๋ค.
- Commit ์ ๊น์ง ์์ ๋ ๋ฐ์ดํฐ๋ ๋ค๋ฅธ ํธ๋์ญ์ ์์ ๋ณผ์ ์๋ค.(MVCC๋ก ๊ฒฉ๋ฆฌ)
2. ํธ๋์ญ์ T2
- T2 ํธ๋์ญ์ ์ T1์ด ์ด๋ ค์๋ ๋์ "0"์ ๋ํด ์ฐ๊ธฐ ์์ ์ ์๋ํ๋ค.
- ๊ทธ๋ฌ๋ T1์์ ๋ฐ์ดํฐ๊ฐ ์์ง Commit ๋์ง ์์๊ธฐ ๋๋ฌธ์ Dirty Read๋ Non-Repeatable Read๋ ๋ฐ์ํ์ง ์๋๋ค.
3. Phantom Read ๋ฐ์ ๊ฐ๋ฅ:
- T2๊ฐ ์๋ก์ด ๋ฐ์ดํฐ +A๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์ญ์ ํ ๊ฒฝ์ฐ, T1 ํธ๋์ญ์
์์ ๋์ผํ SELECT ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ฉด Phantom Read๊ฐ ๋ฐ์ํ ์ ์๋ค.
- ์ด ๊ฒฝ์ฐ MySQL์์๋ Gap Lock์ผ๋ก ๋๋ถ๋ถ์ Phantom Read๋ฅผ ๋ฐฉ์ดํ๋ค.
๐ก Phantom Read์ ๋์ ์์
1. ์ด๊ธฐ ์ํ
- ํ ์ด๋ธ์ id = 1, 2, 3์ธ ๋ ์ฝ๋๊ฐ ์กด์ฌํ๋ค๋ ๊ฐ์
2. ํธ๋์ญ์ A
- SELECT * FROM table WHERE id > 0 ์ฟผ๋ฆฌ๋ฅผ ์คํ โ id = 1, 2, 3 ๊ฒฐ๊ณผ ๋ฐํ.
3. ํธ๋์ญ์ B
- INSERT INTO table (id) VALUES (4) ์คํ ํ COMMIT
4. ํธ๋์ญ์ A (๋ค์ ์คํ)
- ๋์ผํ SELECT * FROM table WHERE id > 0 ์คํ โ ์ถ๊ฐ๋ id = 4 ๋ ์ฝ๋ ํฌํจ.
๊ฒฐ๊ณผ์ ์ผ๋ก, ๊ฐ์ ํธ๋์ญ์ ๋ด์์ ์คํ๋ ๋์ผํ ์ฟผ๋ฆฌ์ง๋ง ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง๋ฉฐ, ์ด๋ฅผ Phantom Read๋ผ๊ณ ํ๋ค.

4. SERIALIZABLE (L3)
- ํน์ง: ๊ฐ์ฅ ๋์ ๊ฒฉ๋ฆฌ ์์ค. ํธ๋์ญ์ ์ ์ง๋ ฌํํ์ฌ ์คํํ๋ค.
- ์ฅ์ : Dirty Read, Non-Repeatable Read, Phantom Read ๋ชจ๋ ๋ฐฉ์งํ๋ค.
- ๋จ์ : ์ฑ๋ฅ ์ ํ(ํธ๋์ญ์ ๊ฐ ๋์์ฑ ๊ฑฐ์ ์์)
- ์ ์ฉ ์ฌ๋ก: ์์ ํ ๋ฐ์ดํฐ ์ ํฉ์ฑ์ด ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ๋ค.
4๏ธโฃ Spring Data JPA์์ ์ค์ ๋ฐฉ๋ฒ
Spring Data JPA์์๋ @Transactional์ ์ฌ์ฉํด ๊ฒฉ๋ฆฌ ์์ค์ ์ค์ ํ ์ ์๋ค.
@Transactional(isolation = Isolation.READ_COMMITTED)
public void dataTransaction() {
// ๋น์ฆ๋์ค ๋ก์ง
}
โน๏ธ ์ฐธ๊ณ
[ASAC 6๊ธฐ ๊ฐ์์๋ฃ]
https://mangkyu.tistory.com/299
[MySQL] ํธ๋์ญ์ ์ ๊ฒฉ๋ฆฌ ์์ค(Isolation Level)์ ๋ํด ์ฝ๊ณ ์๋ฒฝํ๊ฒ ์ดํดํ๊ธฐ
์ด๋ฒ์๋ ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค(Isolation Level)์ ๋ํด ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ์๋์ ๋ด์ฉ์ RealMySQL๊ณผ MySQL ๊ณต์ ๋ฌธ์ ๋ฑ์ ์ฐธ๊ณ ํ์ฌ ์์ฑํ์์ผ๋ฉฐ, ๋ชจ๋ ๋ด์ฉ์ InnoDB๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค๋ช ํฉ๋๋ค. ํด
mangkyu.tistory.com
https://nesoy.github.io/articles/2019-05/Database-Transaction-isolation
ํธ๋์ญ์ ์ ๊ฒฉ๋ฆฌ ์์ค(isolation Level)์ด๋?
nesoy.github.io
'๐ปDEV-STUDY > DataBase' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[DB] ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ์ฅ (Scaling) (0) | 2024.11.29 |
---|---|
[DB] ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋์์ฑ ์ ์ด (Concurrency Control) (1) | 2024.11.29 |
[DB] ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค & ๋น๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค (0) | 2024.11.22 |
ํธ๋์ญ์ ๊ฐ ๋ ๋ฆฝ์ฑ ๋ณด์ฅ
ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค (Isolation Level)
ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ๋ ๋ฒจ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋์์ ์คํ๋๋ ํธ๋์ญ์ ๊ฐ์ ๊ฐ์ญ์ ๊ด๋ฆฌํ๊ธฐ ์ํ ๊ธฐ์ค์ด๋ค. ACID ์์น ์ค "์ผ๊ด์ฑ(Consistency)"๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํ ํต์ฌ ์์์ด๋ค.
1๏ธโฃ ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค์ด๋ ?
ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค์ ์ฌ๋ฌ ํธ๋์ญ์ ์ด ๋์์ ์คํ๋ ๋, ํน์ ํธ๋์ญ์ ์ด ๋ค๋ฅธ ํธ๋์ญ์ ์ ๋ฐ์ดํฐ๋ฅผ ๋ณผ ์ ์๋ ์ ๋๋ฅผ ๊ฒฐ์ ํ๋ ์ค์ ์ด๋ค.
๊ฒฉ๋ฆฌ ์์ค์ ์๋์ ๊ฐ์ด ๋ฎ์ ์์ค(Low Isolation) ์์ ๋์ ์์ค(High Isolation)์ผ๋ก ๋๋๋ค.
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
๊ฒฉ๋ฆฌ ์์ค์ด ๋์์ง์๋ก ๋ฐ์ดํฐ ์ ํฉ์ฑ(Data Integrity)์ด ๊ฐํ๊ฒ ๋ณด์ฅ๋์ง๋ง, ๋์์ ์ฑ๋ฅ ์ ํ๊ฐ ๋ฐ์ํ ์ ์๋ค.
2๏ธโฃ ๊ฒฉ๋ฆฌ ์์ค ๋ณ ๋์๊ณผ ํน์ง
๊ฒฉ๋ฆฌ ์์ค | Dirty Read | Non-Repeatable Read | Phantom Read | ๋์์ฑ |
READ UNCOMMITTED | ๋ฐ์ | ๋ฐ์ | ๋ฐ์ | ๐ฅ ์ต๊ณ |
READ COMMITTED | ๋ฐฉ์ง | ๋ฐ์ | ๋ฐ์ | ๐ ๋์ |
REPEATABLE READ | ๋ฐฉ์ง | ๋ฐฉ์ง | ๋ฐ์(MySQL ๊ฑฐ์ ์์) | ๐ ๋ณดํต |
SERIALIZABLE | ๋ฐฉ์ง | ๋ฐฉ์ง | ๋ฐฉ์ง | ๐ ๋ฎ์ |
3๏ธโฃ ๊ฒฉ๋ฆฌ ์์ค ์์ธ ์ค๋ช
1. READ UNCOMITTED (L0)
- ํน์ง : ์ปค๋ฐ๋์ง ์์ ๋ฐ์ดํฐ๋ ์ฝ์ ์ ์๋ ๊ฐ์ฅ ๋ฎ์ ์์ค์ ๊ฒฉ๋ฆฌ. (ROLLBACK, COMMIT ์ฌ๋ถ์ ์๊ด์์ด ๋ชจ๋ ๊ฐ์ ์ฝ๋๋ค.)
- ์ฅ์ : ์ฑ๋ฅ์ด ๊ฐ์ฅ ๋ฐ์ด๋จ. (๋ฐ์ดํฐ ์ผ๊ด์ฑ ํน์ ์ ํฉ์ฑ์ด ์กฐ๊ธ ๋จ์ด์ง๋๋ผ๋ ์ฑ๋ฅ์ ๊ทน๋ํํ ๋ ์ฌ์ฉํ๋ค.)
- ๋จ์ : Dirty Read, Non-Repeatable Read, Phantom Read ๋ชจ๋ ๋ฐ์ ๊ฐ๋ฅ.
- ์ ์ฉ์ฌ๋ก : "์ฝ๊ธฐ"๊ฐ ๋งค์ฐ ๋น๋ฒํ์ง๋ง ๋ฐ์ดํฐ ์ ํฉ์ฑ์ด ๋ง์ด ํ์ ์๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ ํฉํ๋ค. โ ๊ฑฐ์ ์ฌ์ฉํ์ง ์๋ ์์ค. (๋ฐ์ดํฐ ์ ํฉ์ฑ ๋ฌธ์ )
๐ก ์์: Dirty Read
- ํธ๋์ญ์ A: ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ์ง๋ง ์์ง ์ปค๋ฐํ์ง ์์.
- ํธ๋์ญ์ B: ํธ๋์ญ์ A์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์.
- ํธ๋์ญ์ A๊ฐ ROLLBACK ํ๋ฉด, ํธ๋์ญ์ B๋ ์๋ชป๋ ๋ฐ์ดํฐ๋ฅผ ์ฐธ์กฐํ๊ฒ ๋๋ค.

2. READ COMMITTED (L1)
- ํน์ง: ์ปค๋ฐ๋ ๋ฐ์ดํฐ๋ง ์ฝ์ ์ ์๋ค.
- ์ฅ์ : Dirty Read๋ ๋ฐฉ์ง๋๋ค.
- ๋จ์ : Non-Repeatable Read, Phantom Read ๋ฐ์ ๊ฐ๋ฅ.
- ์ ์ฉ ์ฌ๋ก: ์ค๋ผํด์ ๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ ์์ค์ผ๋ก, ๋ฐ์ดํฐ ์ ํฉ์ฑ๊ณผ ๋์์ฑ์ด ํ์ํ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค. โ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ๊ฒฉ๋ฆฌ ์์ค์ผ๋ก, ์ปค๋ฐ๋์ง ์์ ์ ๋ณด๋ ์ฝ์ ์ ์๋ค.
๐ก ์์: Non-Repeatable Read
- ํธ๋์ญ์ A: ๋ฐ์ดํฐ๋ฅผ ์ฝ์
- ํธ๋์ญ์ B: ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ๊ณ ์ปค๋ฐ.
- ํธ๋์ญ์ A๊ฐ ๋ค์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ผ๋ฉด ๊ฐ์ด ๋ณ๊ฒฝ๋๋ค.

๐ก MVCC์ READ COMMITTED
READ COMMITTED๋ถํฐ MVCC(Mulitiversion Concurrency Control, ๋ค์ค ๋ฒ์ ๋์์ฑ ์ ์ด) ๊ฐ ์ ์ฉ๋๋ค.
MVCC๋ ํธ๋์ญ์ ๋์์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํด ๋ฐ์ดํฐ์ ์ฌ๋ฌ ๋ฒ์ (Snapshots)์ ๊ด๋ฆฌํ๋ฉฐ, Lock ์์ด๋ ์ผ๊ด๋ ๋ฐ์ดํฐ ์ฝ๊ธฐ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ค.
MVCC ๋์ ์๋ฆฌ
- ๋ฐ์ดํฐ ๋ณ๊ฒฝ ์ Undo ์์ญ์ ์๋ณธ ๋ฐ์ดํฐ ๋ฐฑ์
:
- ๋ฐ์ดํฐ๋ ํ ์ด๋ธ์ ์ฆ์ ๋ฐ์๋์ง๋ง, ์ด์ ๋ฐ์ดํฐ๋ Undo ์์ญ์ ์ ์ฅ.
- ํธ๋์ญ์
์์ ์ Snapshot ์์ฑ:
- Snapshot์ Undo์์ญ์ ๊ธฐ๋ฐ์ผ๋ก ํธ๋์ญ์ ์ด ์ฝ์ ๋ฐ์ดํฐ๋ฅผ ๊ฒฐ์ ํ๋ค.
- Garbage Collection์ผ๋ก ๋ถํ์ํ Undo ๋ฐ์ดํฐ ์ญ์ :
- ํ์ ์์ด์ง Undo ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ธฐ์ ์ผ๋ก ์ ๋ฆฌํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํ๋ค.
MySQL(InnoDB)์์์ MVCC
- MySQL(InnoDB)์์๋ Undo ์์ญ์ ํ์ฉํ์ฌ MVCC๋ฅผ ์ง์ํ๋ค.
- ์ฃผ์ ๋์:
- Consistent Read(์ผ๊ด๋ ์ฝ๊ธฐ): ํธ๋์ญ์ ์ ํ ์ด๋ธ์ ์ค์ ๋ฐ์ดํฐ๊ฐ ์๋ Undo ์์ญ์ Snapshot ๋ฐ์ดํฐ๋ฅผ ์ฝ์.
- Dirty Read ๋ฐฉ์ง: ์ปค๋ฐ๋์ง ์์ ๋ฐ์ดํฐ๋ Undo์์ญ์ ํตํด ๋ฐฐ์ .
- ์ฃผ์: Undo ์์ญ์ด ๊ณผ๋ํ๊ฒ ์์ด๋ฉด Garbage Collection์ ๋ฐ๋ฅธ ์ฑ๋ฅ ์ ํ ๊ฐ๋ฅ.
PorstgreSQL์์์ MVCC
- PostgreSQL์ Snapshot Isolation ๋ฐฉ์์ ์ฌ์ฉํ์ฌ MVCC๋ฅผ ์ง์ํ๋ค.
- ์ฃผ์ ๋์:
- ๋ฐ์ดํฐ ๋ณ๊ฒฝ ์ ํธ๋์ญ์ ์์ ์์ ์ Snapshot์ ์ฐธ์กฐํ๋ค.
- First-Commiter Win : ๋์์ ๋์ผ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ค๋ ๊ฒฝ์ฐ, ๋จผ์ ์ปค๋ฐํ ํธ๋์ญ์ ๋ง ์ฑ๊ณตํ๋ค..
3. REPEATABLE READ (L2) (MySQL ๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ ์์ค)
- ํน์ง: ๋์ผ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณต ์ฝ์ ๋ ํญ์ ๊ฐ์ ๊ฐ ๋ฐํ (MVCC ์ฌ์ฉ)
- ์ฅ์ : Dirty Read์ Non-Repeatable Read ๋ฐฉ์ง.
- ๋จ์ : Phantom Read ๊ฐ๋ฅ (MySQL์์๋ ๊ฑฐ์ ๋ฐ์ํ์ง ์๋๋ค)
- ์ ์ฉ ์ฌ๋ก: ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ด ์ค์ํ ์ดํ๋ฆฌ์ผ์ด์ .
๐ก MySQL์ MVCC์ Phantom Read ๋ฐฉ์ง
- MySQL์ ๊ฐญ ๋ฝ(Gap Lock)๊ณผ ๋ฅ์คํธ ํค ๋ฝ(Next-Key Lock)์ ์ฌ์ฉํ์ฌ Phantom Read๋ฅผ ๋ฐฉ์งํ๋ค.
- ๊ทธ๋ฌ๋ ์ ๊ธ ์๋ SELECT๋ก ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ๊ฒฝ์ฐ์๋ Phantom Read๊ฐ ๋ฐ์ํ ์ ์๋ค.
๐ก REPEATABLE READ์ Phantom Read
REPEATABLE READ๋ ํธ๋์ญ์ ๋ด์ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณตํด์ ์ฝ์ ๋ ํญ์ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ T๋ณด์ฅํ๋ค.
๊ทธ๋ฌ๋ ์๋ก์ด ๋ ์ฝ๋๊ฐ ์ถ๊ฐ๋๊ฑฐ๋ ์ญ์ ๋๋ ๊ฒฝ์ฐ(UPDATE X), Phantom Read ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ์๋ค.

1. ํธ๋์ญ์ T1
- T1 ํธ๋์ญ์ ์ ๋ฐ์ดํฐ "0"๋ฅผ ์กฐํ ํ ์์ (+A, -A) ์์ ์ ์ํํ๋ค.
- Commit ์ ๊น์ง ์์ ๋ ๋ฐ์ดํฐ๋ ๋ค๋ฅธ ํธ๋์ญ์ ์์ ๋ณผ์ ์๋ค.(MVCC๋ก ๊ฒฉ๋ฆฌ)
2. ํธ๋์ญ์ T2
- T2 ํธ๋์ญ์ ์ T1์ด ์ด๋ ค์๋ ๋์ "0"์ ๋ํด ์ฐ๊ธฐ ์์ ์ ์๋ํ๋ค.
- ๊ทธ๋ฌ๋ T1์์ ๋ฐ์ดํฐ๊ฐ ์์ง Commit ๋์ง ์์๊ธฐ ๋๋ฌธ์ Dirty Read๋ Non-Repeatable Read๋ ๋ฐ์ํ์ง ์๋๋ค.
3. Phantom Read ๋ฐ์ ๊ฐ๋ฅ:
- T2๊ฐ ์๋ก์ด ๋ฐ์ดํฐ +A๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์ญ์ ํ ๊ฒฝ์ฐ, T1 ํธ๋์ญ์
์์ ๋์ผํ SELECT ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ฉด Phantom Read๊ฐ ๋ฐ์ํ ์ ์๋ค.
- ์ด ๊ฒฝ์ฐ MySQL์์๋ Gap Lock์ผ๋ก ๋๋ถ๋ถ์ Phantom Read๋ฅผ ๋ฐฉ์ดํ๋ค.
๐ก Phantom Read์ ๋์ ์์
1. ์ด๊ธฐ ์ํ
- ํ ์ด๋ธ์ id = 1, 2, 3์ธ ๋ ์ฝ๋๊ฐ ์กด์ฌํ๋ค๋ ๊ฐ์
2. ํธ๋์ญ์ A
- SELECT * FROM table WHERE id > 0 ์ฟผ๋ฆฌ๋ฅผ ์คํ โ id = 1, 2, 3 ๊ฒฐ๊ณผ ๋ฐํ.
3. ํธ๋์ญ์ B
- INSERT INTO table (id) VALUES (4) ์คํ ํ COMMIT
4. ํธ๋์ญ์ A (๋ค์ ์คํ)
- ๋์ผํ SELECT * FROM table WHERE id > 0 ์คํ โ ์ถ๊ฐ๋ id = 4 ๋ ์ฝ๋ ํฌํจ.
๊ฒฐ๊ณผ์ ์ผ๋ก, ๊ฐ์ ํธ๋์ญ์ ๋ด์์ ์คํ๋ ๋์ผํ ์ฟผ๋ฆฌ์ง๋ง ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง๋ฉฐ, ์ด๋ฅผ Phantom Read๋ผ๊ณ ํ๋ค.

4. SERIALIZABLE (L3)
- ํน์ง: ๊ฐ์ฅ ๋์ ๊ฒฉ๋ฆฌ ์์ค. ํธ๋์ญ์ ์ ์ง๋ ฌํํ์ฌ ์คํํ๋ค.
- ์ฅ์ : Dirty Read, Non-Repeatable Read, Phantom Read ๋ชจ๋ ๋ฐฉ์งํ๋ค.
- ๋จ์ : ์ฑ๋ฅ ์ ํ(ํธ๋์ญ์ ๊ฐ ๋์์ฑ ๊ฑฐ์ ์์)
- ์ ์ฉ ์ฌ๋ก: ์์ ํ ๋ฐ์ดํฐ ์ ํฉ์ฑ์ด ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ๋ค.
4๏ธโฃ Spring Data JPA์์ ์ค์ ๋ฐฉ๋ฒ
Spring Data JPA์์๋ @Transactional์ ์ฌ์ฉํด ๊ฒฉ๋ฆฌ ์์ค์ ์ค์ ํ ์ ์๋ค.
@Transactional(isolation = Isolation.READ_COMMITTED)
public void dataTransaction() {
// ๋น์ฆ๋์ค ๋ก์ง
}
โน๏ธ ์ฐธ๊ณ
[ASAC 6๊ธฐ ๊ฐ์์๋ฃ]
https://mangkyu.tistory.com/299
[MySQL] ํธ๋์ญ์ ์ ๊ฒฉ๋ฆฌ ์์ค(Isolation Level)์ ๋ํด ์ฝ๊ณ ์๋ฒฝํ๊ฒ ์ดํดํ๊ธฐ
์ด๋ฒ์๋ ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค(Isolation Level)์ ๋ํด ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ์๋์ ๋ด์ฉ์ RealMySQL๊ณผ MySQL ๊ณต์ ๋ฌธ์ ๋ฑ์ ์ฐธ๊ณ ํ์ฌ ์์ฑํ์์ผ๋ฉฐ, ๋ชจ๋ ๋ด์ฉ์ InnoDB๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค๋ช ํฉ๋๋ค. ํด
mangkyu.tistory.com
https://nesoy.github.io/articles/2019-05/Database-Transaction-isolation
ํธ๋์ญ์ ์ ๊ฒฉ๋ฆฌ ์์ค(isolation Level)์ด๋?
nesoy.github.io
'๐ปDEV-STUDY > DataBase' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[DB] ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ์ฅ (Scaling) (0) | 2024.11.29 |
---|---|
[DB] ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋์์ฑ ์ ์ด (Concurrency Control) (1) | 2024.11.29 |
[DB] ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค & ๋น๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค (0) | 2024.11.22 |