πŸ—ƒοΈ λ°μ΄ν„°λ² μ΄μŠ€

νŠΈλžœμž­μ…˜μ΄λž€ ?

mallin 2025. 3. 15. 01:50

1. νŠΈλžœμž­μ…˜μ΄λž€ ?

νŠΈλžœμž­μ…˜μ„ ν•œλ§ˆλ””λ‘œ μ„€λͺ…ν•˜μžλ©΄ "λͺ¨λ“  λͺ…λ Ήμ–΄μ˜ 성곡 λ˜λŠ” μ‹€νŒ¨λ₯Ό ν•œκΊΌλ²ˆμ— λͺ¨μ•„μ„œ μ²˜λ¦¬ν•˜λŠ” 것" ν•˜κ³  ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

만일, μ—¬λŸ¬ λͺ…λ Ήμ–΄λ₯Ό ν•œ λ²ˆμ— μ²˜λ¦¬ν•˜λ‹€κ°€ κ·Έ 쀑 ν•˜λ‚˜λΌλ„ μ‹€νŒ¨ν•˜λ©΄, νŠΈλžœμž­μ…˜ λ‚΄μ˜ λͺ¨λ“  λͺ…λ Ήμ–΄κ°€ λ¬΄νš¨ν™”(λ‘€λ°±)λ©λ‹ˆλ‹€.

 

πŸ’° 예λ₯Ό λ“€μ–΄, μ€ν–‰μ—μ„œ λ‹€λ₯Έ κ³„μ’Œλ‘œ λˆμ„ μ†‘κΈˆν•˜λŠ” 상황을 κ°€μ •ν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€. 

1. λ‚΄ κ³„μ’Œμ—μ„œ λˆμ„ μΆœκΈˆν•˜κ³ 

2. λ‹€λ₯Έ κ³„μ’Œλ‘œ λˆμ„ μž…κΈˆν•˜λ©΄ μ†‘κΈˆμ΄ μ„±κ³΅ν•©λ‹ˆλ‹€ !

 

ν•˜μ§€λ§Œ, λ§Œμ•½ λ‘λ²ˆμ§Έ κ³Όμ •μ—μ„œ 였λ₯˜κ°€ λ°œμƒν•΄ μž…κΈˆμ΄ λ˜μ§€ μ•ŠμœΌλ©΄, 돈이 μ–΄λ”˜κ°€λ‘œ μ‚¬λΌμ§€κ²Œ λ©λ‹ˆλ‹€ πŸ€”

이런 상황을 λ°©μ§€ν•˜κΈ° μœ„ν•΄μ„œλŠ”, 1번과 2번 과정을 ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜μœΌλ‘œ λ¬Άμ–΄μ•Ό ν•©λ‹ˆλ‹€ 

μ΄λ ‡κ²Œ ν•˜λ©΄ λ‘˜ 쀑 ν•˜λ‚˜λΌλ„ μ‹€νŒ¨ν•˜λ©΄ 전체 νŠΈλžœμž­μ…˜μ΄ λ‘€λ°±λ˜μ–΄, 였λ₯˜λ₯Ό λ°©μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. !


2. νŠΈλžœμž­μ…˜μ˜ μ„±μ§ˆ

νŠΈλžœμž­μ…˜μ€ ACID 라고 λΆˆλ¦¬λŠ” 총 4κ°€μ§€μ˜ μ„±μ§ˆμ„ κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€. 

μ„±μ§ˆ μ„€λͺ… μ˜ˆμ‹œ
A tomicity (μ›μžμ„±) νŠΈλžœμž­μ…˜μ€ λΆ€λΆ„μ μœΌλ‘œ μ™„λ£Œλ  수 μ—†μœΌλ©°, 전체가 μ™„λ£Œλ˜κ±°λ‚˜ μ•„μ˜ˆ μ‹€ν–‰λ˜μ§€ μ•Šμ•„μ•Ό ν•œλ‹€. 좜금만 μ„±κ³΅ν•˜κ³  μž…κΈˆμ΄ μ‹€νŒ¨ν•˜λ©΄ μ•ˆ λœλ‹€.
C onsistency (일관성) νŠΈλžœμž­μ…˜μ΄ μ„±κ³΅μ μœΌλ‘œ μ™„λ£Œλ˜λ©΄ 항상 일관성 μžˆλŠ” λ°μ΄ν„°λ² μ΄μŠ€ μƒνƒœλ‘œ μœ μ§€λ˜μ–΄μ•Ό ν•œλ‹€. κ³„μ’Œ 이체 μ „κ³Ό ν›„μ˜ 돈의 합이 κ°™μ•„μ•Ό ν•œλ‹€.
I solation (독립성,격리성) νŠΈλžœμž­μ…˜ μˆ˜ν–‰ 쀑 λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ˜ μž‘μ—…μ΄ 끼어듀지 μ•Šλ„λ‘ 보μž₯λœλ‹€. 좜금 ν›„, λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ΄ λ‚΄ κ³„μ’Œμ˜ κΈˆμ•‘μ„ μˆ˜μ •ν•˜μ§€ λͺ»ν•˜λ„둝 ν•΄μ•Ό ν•œλ‹€.
D urablility (μ˜μ†μ„±,지속성) μ„±κ³΅μ μœΌλ‘œ μˆ˜ν–‰λœ νŠΈλžœμž­μ…˜μ€ μ‹œμŠ€ν…œ μž₯μ• κ°€ λ°œμƒν•˜λ”λΌλ„ 영ꡬ적으둜 λ°˜μ˜λœλ‹€. μ‹œμŠ€ν…œμ— λ¬Έμ œκ°€ 생기더라도, μ»€λ°‹λœ λ°μ΄ν„°λŠ” DB에 영ꡬ적으둜 λ°˜μ˜λ˜μ–΄μ•Ό ν•œλ‹€.

 

ν•˜μ§€λ§Œ ACID 원칙을 μ™„λ²½ν•˜κ²Œ μ§€ν‚€λ©΄ λ™μ‹œμ„±μ΄ λ–¨μ–΄μ§€κ²Œ λ©λ‹ˆλ‹€ ⬇️

κ·Έλ ‡κΈ° λ•Œλ¬Έμ— ACID 원칙을 ν¬μƒν•˜μ—¬ λ™μ‹œμ„±μ„ 얻을 수 μžˆλŠ” 방법인 격리 μˆ˜μ€€ (isolation level) 을 μ‘°μ •ν•  수 μžˆλŠ” 방법을 μ œκ³΅ν•©λ‹ˆλ‹€

 


3. νŠΈλžœμž­μ…˜ 격리 μˆ˜μ€€ (isolation level)

격리 μˆ˜μ€€μ€ 3κ°€μ§€ λ¬Έμ œκ°€ λ°œμƒν•˜λŠ”μ§€μ— λ”°λΌμ„œ λΆ„λ₯˜ν•©λ‹ˆλ‹€. 

1. Dirty Read

2. Non-Repeatable Read 

3. Phantom Read

 

 

3-1. Dirty Read (비컀밋 읽기)

νŠΈλžœμž­μ…˜μ—μ„œ μ»€λ°‹λ˜κΈ° μ „ μž‘μ—… λ‚΄μš©μ„ λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œ λ³Ό 수 μž‡λŠ” ν˜„μƒμ„ Dirty Read 라고 ν•©λ‹ˆλ‹€.

 

예λ₯Ό λ“€μ–΄μ„œ 

  • νŠΈλžœμž­μ…˜ A μ—μ„œ id: 22, name: 이름인 row λ₯Ό insert ν•˜κ³  μ»€λ°‹ν•˜μ§€ μ•Šμ€ μƒνƒœμ—μ„œ, 
  • νŠΈλžœμž­μ…˜ B κ°€ id: 22 λ₯Ό select ν•˜λ©΄, B λŠ” A 의 데이터λ₯Ό 읽을 수 μžˆμŠ΅λ‹ˆλ‹€. 
  • μ΄λ•Œ A νŠΈλžœμž­μ…˜μ΄ μ»€λ°‹λ˜μ§€ μ•Šκ³  둀백되면, νŠΈλžœμž­μ…˜ B λŠ” 잘λͺ»λœ 데이터λ₯Ό 읽은 μ…ˆμ΄ λ˜μ–΄ 데이터 정합성에 λ¬Έμ œκ°€ μƒκΉλ‹ˆλ‹€ πŸ’₯

 

이게 κ°€λŠ₯ν•œ μ΄μœ λŠ” λ°”λ‘œ InnoDB 엔진이 νŠΈλžœμž­μ…˜μ„ μ»€λ°‹ν•˜λŠ” 방식 λ•Œλ¬Έμž…λ‹ˆλ‹€. 

InnoDB λŠ” μ»€λ°‹λ˜μ§€ μ•Šμ€ μž‘μ—…μ΄λΌλ„ μ‹€ν–‰ν•œ 쿼리λ₯Ό DB 에 μ μš©ν•©λ‹ˆλ‹€. 

즉, logλ₯Ό 보고 νŠΉμ • μ‹œμ μ˜ snapshot 을 λ³΅κ΅¬ν•˜λŠ” consistent read λ₯Ό ν•˜μ§€ μ•Šκ³ , ν•΄λ‹Ή μ‹œμ μ˜ DB λ₯Ό λ°”λ‘œ 읽으면 Dirty Read κ°€ λ°œμƒν•©λ‹ˆλ‹€. 

consistent read λž€ ?
SELECT μ‹œ ν˜„μž¬ DB 값이 μ•„λ‹Œ νŠΉμ • μ‹œμ μ˜ DB snapshot 을 μ½μ–΄μ˜€λŠ” 방식을 μ˜λ―Έν•©λ‹ˆλ‹€. 
ν•΄λ‹Ή snapshot 은 μ»€λ°‹λœ λ³€ν™”λ§Œμ„ ν¬ν•¨ν•˜κ³  있으며, InnoDB λŠ” 쿼리 μ‹€ν–‰ μ‹œ ν•΄λ‹Ή μ‹œμ μ˜ DB snapshot 을 λ³΅κ΅¬ν•˜κΈ° μœ„ν•΄ log λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

 

 

3-2. Non-Repeatable Read (λΉ„λ°˜λ³΅ 읽기)

ν•œ νŠΈλžœμž­μ…˜μ—μ„œ 같은 쿼리λ₯Ό 두 번 μ‹€ν–‰ν–ˆμ„ λ•Œ κ·Έ 사이에 λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ΄ 값을 μˆ˜μ •ν•˜κ±°λ‚˜ μ‚­μ œν•˜μ—¬ 두 쿼리의 κ²°κ³Όκ°€ λ‹¬λΌμ§€λŠ” ν˜„μƒμ„ μ˜λ―Έν•©λ‹ˆλ‹€. 

 

예λ₯Ό λ“€μ–΄μ„œ

 

  • νŠΈλžœμž­μ…˜ Aκ°€ SELECT balance FROM account WHERE id = 1을 μ‹€ν–‰ν•˜μ—¬ κ³„μ’Œ μž”μ•‘μ„ μ‘°νšŒν•©λ‹ˆλ‹€.
  • κ·Έ 사이에 νŠΈλžœμž­μ…˜ Bκ°€ ν•΄λ‹Ή κ³„μ’Œμ˜ μž”μ•‘μ„ μ—…λ°μ΄νŠΈν•˜κ±°λ‚˜ μ‚­μ œν•©λ‹ˆλ‹€.
  • νŠΈλžœμž­μ…˜ Aκ°€ λ‹€μ‹œ 같은 쿼리λ₯Ό μ‹€ν–‰ν•˜λ©΄, 두 번째 κ²°κ³ΌλŠ” 첫 λ²ˆμ§Έμ™€ λ‹¬λΌμ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.

이둜 인해 ν•œ νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ 일관성 μ—†λŠ” κ²°κ³Όκ°€ λ°œμƒν•©λ‹ˆλ‹€.

 

 

3-3. Phantom Read (가상 읽기)

ν•œ νŠΈλžœμž­μ…˜ μ•ˆμ—μ„œ 일정 λ²”μœ„μ˜ λ ˆμ½”λ“œλ₯Ό λ‘λ²ˆ 이상 읽을 λ•Œ, 첫번째 μΏΌλ¦¬μ—μ„œ μ—†λ˜ λ ˆμ½”λ“œκ°€ λ‘λ²ˆμ§Έ μΏΌλ¦¬μ—μ„œ λ‚˜νƒ€λ‚˜λŠ” ν˜„μƒμ„ μ˜λ―Έν•©λ‹ˆλ‹€.

 

예λ₯Ό λ“€μ–΄μ„œ

  • νŠΈλžœμž­μ…˜ Aκ°€ νŠΉμ • λ²”μœ„μ˜ 데이터λ₯Ό μ‘°νšŒν•˜λŠ” SELECT 쿼리λ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, balance > 1000 쑰건으둜 μ‘°νšŒν•œ κ²°κ³Όκ°€ A νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ 5개의 λ ˆμ½”λ“œλ₯Ό λ°˜ν™˜ν•œλ‹€κ³  κ°€μ •ν•©λ‹ˆλ‹€.
  • κ·Έ 사이에 νŠΈλžœμž­μ…˜ Bκ°€ λ™μΌν•œ λ²”μœ„μ˜ 데이터λ₯Ό μ‚½μž…ν•˜κ±°λ‚˜ μ‚­μ œν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, balance > 1000 쑰건에 λ§žλŠ” μƒˆλ‘œμš΄ λ ˆμ½”λ“œλ₯Ό μ‚½μž…ν•©λ‹ˆλ‹€.
  • νŠΈλžœμž­μ…˜ Aκ°€ λ‹€μ‹œ 같은 λ²”μœ„μ˜ 데이터λ₯Ό μ‘°νšŒν•˜λ©΄, 첫 번째 μΏΌλ¦¬μ—μ„œ μ—†λ˜ λ ˆμ½”λ“œκ°€ 두 번째 μΏΌλ¦¬μ—μ„œ λ‚˜νƒ€λ‚˜λŠ” ν˜„μƒμ΄ λ°œμƒν•©λ‹ˆλ‹€.

이둜 인해, νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ 일관성 μ—†λŠ” 데이터 κ²°κ³Όλ₯Ό 보게 λ˜μ–΄, 데이터 정합성에 λ¬Έμ œκ°€ 생길 수 μžˆμŠ΅λ‹ˆλ‹€.

 

 

3-4. νŠΈλžœμž­μ…˜ 격리 μˆ˜μ€€

μœ„μ˜ 3κ°€μ§€ λ¬Έμ œκ°€ λ°œμƒν•˜λŠ”μ§€ 여뢀에 λ”°λΌμ„œ νŠΈλžœμž­μ…˜ 격리 μˆ˜μ€€μ΄ κ²°μ •λ˜λŠ”λ°, 그건 μ•„λž˜ ν‘œμ™€ 같이 κ²°μ •λ©λ‹ˆλ‹€ 

뢄리 레벨 Dirty Read Non-Repeatable Read Phantom Read
READ UNCOMMITEED O O O
READ COMMITTED - O O
REPEATABLE READ - - O
SERIALIZABLE - - -
  • READ UNCOMMITTED
    • 문제 λ°œμƒ : Dirty Read, Non-Repeatable Read, Phantom Read λ°œμƒ
    • μ»€λ°‹λ˜μ§€ μ•Šμ€ 데이터λ₯Ό 읽을 수 μžˆμŠ΅λ‹ˆλ‹€. 
    • μ˜€λΌν΄μ€ 이 격리 μˆ˜μ€€μ„ μ§€μ›ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 
  • READ COMMITTED
    • 문제 λ°œμƒ : Non-Repeatable Read, Phantom Read λ°œμƒ
    • μ»€λ°‹λœ λ°μ΄ν„°λ§Œ 읽을 수 μžˆμŠ΅λ‹ˆλ‹€.
    • DB2, SQL Server, Sybase 의 경우 S-Lock ν•˜λ‚˜μ˜ λ ˆμ½”λ“œλ₯Ό 읽을 λ•Œ Lock 을 μ„€μ •ν•˜κ³ , ν•΄λ‹Ή λ ˆμ½”λ“œμ—μ„œ λΉ μ§€λŠ” μˆœκ°„ Lock 을 ν•΄μ œν•˜λŠ” λ°©μ‹μœΌλ‘œ S-Lock 을 μ΄μš©ν•΄μ„œ κ΅¬ν˜„ν•©λ‹ˆλ‹€.
  • REPEATABLE READ
    • 문제 λ°œμƒ : Phantom Read λ°œμƒ
    • 같은 νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ λ°˜λ³΅λ˜λŠ” μ‘°νšŒλŠ” 항상 같은 값을 μ‘°νšŒν•©λ‹ˆλ‹€. 
    • νŠΈλžœμž­μ…˜μ΄ μ‹œμž‘λ  λ•Œμ˜ μ‹œμ μ„ κΈ°μ€€μœΌλ‘œ μΌκ΄€λœ 데이터λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€
    • InnoDB 의 κΈ°λ³Έ 격리 μˆ˜μ€€μž…λ‹ˆλ‹€.
  • SERIALIZABLE
    • 문제 λ°œμƒ : λͺ¨λ“  λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 
    • κ°€μž₯ 높은 격리 μˆ˜μ€€μœΌλ‘œ, νŠΈλžœμž­μ…˜μ΄ μ™„λ£Œλ  λ•ŒκΉŒμ§€ 데이터에 λŒ€ν•œ μ—…λ°μ΄νŠΈλ‚˜ μ‚½μž…μ΄ λΆˆκ°€λŠ₯ν•©λ‹ˆλ‹€
    • λͺ¨λ“  SELECT μ—μ„œ ν•΄λ‹Ή 행에 S-Lock 이 κ±Έλ¦¬λ―€λ‘œ λ™μ‹œμ„±μ΄ κ°€μž₯ λ–¨μ–΄μ§€κ³ , Deadlock 이 λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • 많이 μ‚¬μš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

4. β˜•οΈ μŠ€ν”„λ§μ—μ„œ νŠΈλžœμž­μ…˜ μ‚¬μš©ν•˜λŠ” 법

μŠ€ν”„λ§μ—μ„œλŠ” @Transactional μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•΄ νŠΈλžœμž­μ…˜μ„ μ‰½κ²Œ μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 

이 μ–΄λ…Έν…Œμ΄μ…˜μ€ λ©”μ†Œλ“œλ‚˜ ν΄λž˜μŠ€μ— μ μš©ν•  수 있으며, νŠΈλžœμž­μ…˜μ˜ μ‹œμž‘κ³Ό 끝을 μžλ™μœΌλ‘œ κ΄€λ¦¬ν•©λ‹ˆλ‹€ !

import org.springframework.transaction.annotation.Transactional;

@Transactional
class Test {

}

 

μœ„ μ½”λ“œμ²˜λŸΌ @Transactional μ–΄λ…Έν…Œμ΄μ…˜μ„ λ©”μ†Œλ“œλ‚˜ ν΄λž˜μŠ€μ— μΆ”κ°€ν•˜λ©΄ ν•΄λ‹Ή λ©”μ†Œλ“œ λ˜λŠ” 클래슀 λ‚΄μ—μ„œ μˆ˜ν–‰λ˜λŠ” λͺ¨λ“  λ°μ΄ν„°λ² μ΄μŠ€ μž‘μ—…μ΄ νŠΈλžœμž­μ…˜μœΌλ‘œ λ¬Άμž…λ‹ˆλ‹€

 

λ˜ν•œ, κ²©λ¦¬μˆ˜μ€€λ„ μ„€μ •ν•  수 μžˆλŠ”λ°μš”.

@Transactional μ–΄λ…Έν…Œμ΄μ…˜μ—μ„œ isolation 속성을 μ‚¬μš©ν•˜λ©΄ λ©λ‹ˆλ‹€

예λ₯Ό λ“€μ–΄, 격리 μˆ˜μ€€μ„ SERIALIZABLE둜 μ„€μ •ν•˜λ €λ©΄ λ‹€μŒκ³Ό 같이 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Isolation;

@Transactional(isolation = Isolation.SERIALIZABLE)
class Test {
}