ํธ๋์ญ์ ๊ฐ ๋ ๋ฆฝ์ฑ ๋ณด์ฅ
ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค (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
https://nesoy.github.io/articles/2019-05/Database-Transaction-isolation
'๐ปDEV-STUDY > DataBase' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[DB] ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ์ฅ (Scaling) (0) | 2024.11.29 |
---|---|
[DB] ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋์์ฑ ์ ์ด (Concurrency Control) (1) | 2024.11.29 |
[DB] ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค & ๋น๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค (0) | 2024.11.22 |