πŸ›’οΈDatabase

MySQL의 격리 μˆ˜μ€€(Isolation Level)

DevPoong 2023. 9. 11. 13:11

 MySQL의 격리 μˆ˜μ€€

νŠΈλžœμž­μ…˜μ˜ 격리 μˆ˜μ€€(Isolation Level)μ΄λž€ μ—¬λŸ¬ νŠΈλžœμž­μ…˜μ΄ λ™μ‹œμ— 처리될 λ•Œ νŠΉμ • νŠΈλžœμž­μ…˜μ΄ λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œ λ³€κ²½ν•˜κ±°λ‚˜ μ‘°νšŒν•˜λŠ” 데이터λ₯Ό λ³Ό 수 있게 ν—ˆμš©ν• μ§€ 말지λ₯Ό κ²°μ •ν•˜λŠ” 것이닀.

격리 μˆ˜μ€€μ€ 크게 4κ°€μ§€λ‘œ λ‚˜λ‰œλ‹€.

  1. Read UNCOMMITTED
  2. Read COMMITTED
  3. REPEATABLE READ
  4. SERIALIZABLE

1λ²ˆλΆ€ν„° 4λ²ˆκΉŒμ§€ λ’€λ‘œ 갈수둝 각 νŠΈλžœμž­μ…˜ κ°„μ˜ 데이터 격리(고립) 정도가 높아지며, λ™μ‹œ 처리 μ„±λŠ₯도 일반적으둜 λ–¨μ–΄μ§ˆ 수 μžˆλ‹€.
격리 μˆ˜μ€€μ΄ λ†’μ•„μ§ˆμˆ˜λ‘ MySQL μ„œλ²„μ˜ 처리 μ„±λŠ₯이 많이 λ–¨μ–΄μ§ˆ κ²ƒμœΌλ‘œ 생각할 수 μžˆμ§€λ§Œ, 사싀 SERIALIZABLE μˆ˜μ€€μ΄ μ•„λ‹ˆλΌλ©΄ 크게 μ„±λŠ₯ μ €ν•˜κ°€ λ°œμƒν•˜μ§€λŠ” μ•ŠμœΌλ‹ˆ μ•ˆμ‹¬ν•΄λ„ λœλ‹€.

 

ν•˜λ‚˜ νŠΉλ³„ν•œ 뢀뢄이 μžˆλ‹€. SQL-92 or 99 ν‘œμ€€μ— λ”°λ₯΄λ©΄ REPEATABLE READ 격리 μˆ˜μ€€μ—μ„œλŠ” PHANTOM READκ°€ λ°œμƒν•  수 μžˆλ‹€.
ν•˜μ§€λ§Œ, InnoDBλŠ” λ…νŠΉν•œ νŠΉμ„± λ•Œλ¬Έμ— REPEATABLE READ 격리 μˆ˜μ€€μ—μ„œλ„ PHANTOM READκ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. 

 

일반적인 온라인 μ„œλΉ„μŠ€ μš©λ„μ˜ DBμ—μ„œλŠ” READ COMMITTED와 REPETABLE READ 쀑 ν•˜λ‚˜λ₯Ό μ‚¬μš©ν•œλ‹€.
ORACLEκ³Ό 같은 DBMSλŠ” READ COMMITTED μˆ˜μ€€μ„ 많이 μ‚¬μš©ν•˜κ³ , MySQLμ—μ„œλŠ” REPEATABLE READλ₯Ό 주둜 μ‚¬μš©ν•œλ‹€.

 

 

1. READ UNCOMMITTED

각 νŠΈλžœμž­μ…˜μ—μ„œμ˜ λ³€κ²½ λ‚΄μš©μ΄ COMMITμ΄λ‚˜ ROLLBACK 여뢀에 상관없이 λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œ 보인닀.

μ‚¬μš©μž Aκ°€ INSERTλ₯Ό μˆ˜ν–‰ν•œ ν›„ COMMIT ν•˜κΈ°λ„ 전에 μ‚¬μš©μž Bκ°€ ν•΄λ‹Ή 데이터λ₯Ό κ²€μƒ‰ν•˜λŠ” 경우, 이λ₯Ό 막지 μ•ŠλŠ”λ‹€. 
이 μƒν™©μ—μ„œ μ‚¬μš©μž Aκ°€ 처리 도쀑 μ–΄λ– ν•œ 문제둜 인해 ROLLBACK을 μ§„ν–‰ν•œλ‹€λ©΄ μ—¬μ „νžˆ μ‚¬μš©μž BλŠ” μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 데이터λ₯Ό 가지고 μž‘μ—…μ„ 진행할 κ²ƒμ΄λΌλŠ” 것이닀.

 

문제점

이처럼 μ–΄λ–€ νŠΈλžœμž­μ…˜μ—μ„œ μ²˜λ¦¬ν•œ μž‘μ—…μ΄ μ™„λ£Œλ˜μ§€ μ•Šμ•˜μŒμ—λ„ λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œ λ³Ό 수 μžˆλŠ” ν˜„μƒμ„ Dirty Read라고 ν•œλ‹€.
μ΄λŸ¬ν•œ 문제 λ•Œλ¬Έμ— READ UNCOMMITTEDλŠ” RDBMS ν‘œμ€€μ—μ„œλŠ” νŠΈλžœμž­μ…˜μ˜ 격리 μˆ˜μ€€μœΌλ‘œ μΈμ •ν•˜μ§€ μ•Šμ„ μ •λ„λ‘œ 정합성에 λ¬Έμ œκ°€ λ§Žλ‹€.

MySQL을 μ‚¬μš©ν•œλ‹€λ©΄ μ΅œμ†Œν•œ READ COMMITTED μ΄μƒμ˜ 격리 μˆ˜μ€€μ„ μ‚¬μš©ν•  것!

 

 

2. READ COMMITTED

Oracle DBMSμ—μ„œ 기본으둜 μ‚¬μš©λ˜λŠ” 격리 μˆ˜μ€€μ΄λ©°, 온라인 μ„œλΉ„μŠ€μ—μ„œ κ°€μž₯ 많이 μ„ νƒλ˜λŠ” 격리 μˆ˜μ€€μ΄λ‹€.

ν•΄λ‹Ή 격리 μˆ˜μ€€λΆ€ν„°λŠ” Dirty Read와 같은 ν˜„μƒμ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.
μ–΄λ– ν•œ νŠΈλžœμž­μ…˜μ΄ 데이터λ₯Ό λ³€κ²½ν–ˆλ”λΌλ„ COMMIT이 μ™„λ£Œλœ λ°μ΄ν„°λ§Œ λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œ μ‘°νšŒν•  수 있기 λ•Œλ¬Έμ΄λ‹€.

READ COMMITTED 격리 μˆ˜μ€€μ—μ„œλŠ” 언두 둜그λ₯Ό μ‚¬μš©ν•œλ‹€.
데이터 변경이 λ°œμƒν•˜λ©΄ 언두 둜그 μ˜μ—­μ— 이전 λ ˆμ½”λ“œ 정보가 λ°±μ—…λœλ‹€. λ”°λΌμ„œ μ‚¬μš©μž Aκ°€ 데이터λ₯Ό λ³€κ²½ν•˜κ³  아직 COMMIT이 되기 전이라면 μ‚¬μš©μž BλŠ” ν…Œμ΄λΈ”μ„ μ‘°νšŒν•˜λŠ” 것이 μ•„λ‹ˆλΌ 언두 μ˜μ—­μ— λ°±μ—…λœ λ ˆμ½”λ“œλ₯Ό κ°€μ Έμ˜¨λ‹€.

 

문제점

READ COMMITTED 격리 μˆ˜μ€€μ—μ„œλ„ NON-REPEATABLE READλΌλŠ” λ ˆμ½”λ“œκ°€ λ°˜λ³΅λ˜μ–΄ μ½μ–΄μ§ˆ λ•Œ λ°œμƒν•˜λŠ” 데이터 λΆ€μ •ν•© λ¬Έμ œκ°€ μžˆλ‹€.

기본적으둜 ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ λ˜‘κ°™μ€ SELECT 쿼리λ₯Ό μ‹€ν–‰ν–ˆμ„ λ•Œ 항상 같은 κ²°κ³Όλ₯Ό 가져와야 ν•œλ‹€λŠ” REPEATABLE READ 정합성에 λ”°λ₯Ό 수 μžˆμ–΄μ•Ό ν•œλ‹€.

ν•˜μ§€λ§Œ, ν•΄λ‹Ή 격리 μˆ˜μ€€μ—μ„œλŠ” μ‚¬μš©μž Bκ°€ λ¨Όμ € νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν•˜κ³  처음 νŠΉμ • 쑰건으둜 λ ˆμ½”λ“œλ₯Ό κ²€μƒ‰ν–ˆμ„ λ•ŒλŠ” κ²°κ³Όκ°€ μ—†μ—ˆμ§€λ§Œ κ·Έ 사이에 μ‚¬μš©μž Aκ°€ μƒˆλ‘œμš΄ 데이터λ₯Ό COMMIT ν•˜μ˜€κ³ , λ‹€μ‹œ μ‚¬μš©μž Bκ°€ 같은 쑰건으둜 λ ˆμ½”λ“œλ₯Ό κ²€μƒ‰ν•˜λ©΄ 데이터가 1개 κ²€μƒ‰λ˜λŠ” 문제인 것이닀. μ΄λŠ” REPEATABLE READ 정합성에 μ–΄κΈ‹λ‚˜λŠ” 것이닀.

 

μ΄λŸ¬ν•œ λΆ€μ •ν•© ν˜„μƒμ€ 일반적인 μƒν™©μ—μ„œλŠ” λ¬Έμ œκ°€ λ˜μ§€ μ•Šμ„ 수 μžˆμ§€λ§Œ ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜μ—μ„œ λ™μΌν•œ 데이터λ₯Ό μ—¬λŸ¬ 번 읽고 λ³€κ²½ν•˜λŠ” μž‘μ—…μ΄ κΈˆμ „μ μœΌλ‘œ κ΄€λ ¨λ˜λ©΄ λ¬Έμ œκ°€ 될 수 μžˆλ‹€.

 

 

3. REPETABLE READ

ν•΄λ‹Ή 격리 μˆ˜μ€€μ€ MySQL의 InnoDB μŠ€ν† λ¦¬μ§€ μ—”μ§„μ—μ„œ 기본적으둜 μ‚¬μš©λœλ‹€. λ°”μ΄λ„ˆλ¦¬ 둜그λ₯Ό 가진 MySQL μ„œλ²„μ—μ„œλŠ” μ΅œμ†Œ REPEATABLE READ 격리 μˆ˜μ€€ 이상을 μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.

νŠΈλžœμž­μ…˜ λ‚΄λΆ€μ—μ„œ μ‹€ν–‰λ˜λŠ” SELECT와 μ™ΈλΆ€μ—μ„œ μ‹€ν–‰λ˜λŠ” SELECT의 차이가 μ—†λŠ” READ-COMMITTED 격리 μˆ˜μ€€κ³ΌλŠ” λ‹€λ₯΄κ²Œ,
REPEATABLE READ 격리 μˆ˜μ€€μ€ 기본적으둜 SELECT 쿼리 λ¬Έμž₯도 νŠΈλžœμž­μ…˜ λ²”μœ„ λ‚΄μ—μ„œλ§Œ λ™μž‘ν•œλ‹€.

 

ν•΄λ‹Ή 격리 μˆ˜μ€€ λΆ€ν„°λŠ” NON-REPEATABLE READ ν˜„μƒμ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.  InnoDB μŠ€ν† λ¦¬μ§€ 엔진은 νŠΈλžœμž­μ…˜μ΄ ROLLBACK 될 κ°€λŠ₯성에 λŒ€λΉ„ν•΄ λ³€κ²½λ˜κΈ° μ „ λ ˆμ½”λ“œλ₯Ό 언두 곡간에 λ°±μ—…ν•΄ 두고 μ‹€μ œ λ ˆμ½”λ“œ 값을 λ³€κ²½ν•œλ‹€.
μ΄λŸ¬ν•œ λ³€κ²½ 방식을 MVCC(Multi Version Concurrency Control) 이라고 ν•œλ‹€.

 

REPEATABLE READλŠ” MVCCλ₯Ό μœ„ν•΄ 언두 μ˜μ—­μ— λ°±μ—…λœ 이전 데이터λ₯Ό μ΄μš©ν•΄ 동일 νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œλŠ” λ™μΌν•œ κ²°κ³Όλ₯Ό 보여쀄 수 있게 보μž₯ν•œλ‹€.
READ_COMMITTED 격리 μˆ˜μ€€ λ˜ν•œ MVCCλ₯Ό μ΄μš©ν•΄ COMMIT 되기 μ „μ˜ 데이터λ₯Ό λ³΄μ—¬μ£ΌκΈ°λŠ” ν•œλ‹€. ν•˜μ§€λ§Œ, μ°¨μ΄λŠ” 언두 μ˜μ—­μ— λ°±μ—…λœ λ ˆμ½”λ“œμ˜ μ—¬λŸ¬ 버전 κ°€μš΄λ° λͺ‡ 번째 이전 λ²„μ „κΉŒμ§€ μ°Ύμ•„ λ“€μ–΄κ°€μ•Ό ν•˜λŠλƒμ— μžˆλ‹€.

 

λͺ¨λ“  InnoDB의 νŠΈλžœμž­μ…˜μ€ κ³ μœ ν•œ νŠΈλžœμž­μ…˜ 번호(순차 증가)λ₯Ό 가진닀. 언두 μ˜μ—­μ— λ°±μ—…λœ λͺ¨λ“  λ ˆμ½”λ“œμ—λŠ” 변경을 λ°œμƒμ‹œν‚¨ νŠΈλžœμž­μ…˜μ˜ λ²ˆν˜Έκ°€ ν¬ν•¨λœλ‹€. 그리고 언두 μ˜μ—­μ˜ λ°±μ—…λœ λ°μ΄ν„°λŠ” InnoDB μŠ€ν† λ¦¬μ§€ 엔진이 λΆˆν•„μš”ν•˜λ‹€κ³  νŒλ‹¨λ˜λŠ” μ‹œμ μ— 주기적으둜 μ‚­μ œν•œλ‹€.

μ‹€ν–‰ 쀑인 νŠΈλžœμž­μ…˜ 쀑에 κ°€μž₯ 였래된 νŠΈλžœμž­μ…˜ 번호λ₯Ό κΈ°μ€€μœΌλ‘œ 그보닀 μ•žμ„  νŠΈλžœμž­μ…˜ 번호λ₯Ό 가진 언두 μ˜μ—­μ˜ νŠΉμ • ꡬ간 λ°μ΄ν„°λŠ” μ‚­μ œν•  수 μ—†κ³  보쑴해야 ν•œλ‹€.

 

μœ„ κ·Έλ¦Ό μ˜ˆμ‹œμ—μ„œ μ‚¬μš©μž A의 νŠΈλžœμž­μ…˜ λ²ˆν˜ΈλŠ” 12이고, μ‚¬μš©μž BλŠ” 10이닀. μ΄λ•Œ μ‚¬μš©μž Aκ°€ λ ˆμ½”λ“œλ₯Ό λ³€κ²½ν–ˆλ‹€κ³  ν•˜λ”λΌλ„ μ‚¬μš©μž BλŠ” μžμ‹ λ³΄λ‹€ μž‘μ€ νŠΈλžœμž­μ…˜ 번호 즉, 10보닀 μž‘μ€ νŠΈλžœμž­μ…˜ 번호λ₯Ό 가진 λ³€κ²½μ‚¬ν•­λ§Œμ„ 보게 λœλ‹€.

 

문제점

REPEATABLE READ 격리 μˆ˜μ€€μ—μ„œλ„ PHANTOM READ λΆ€μ •ν•© ν˜„μƒμ΄ λ°œμƒν•  수 μžˆλ‹€. 

REPEATABLE READμ—μ„œλŠ” ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜μ—μ„œ 두 번의 SELECT 쿼리에 λŒ€ν•œ κ²°κ³ΌλŠ” λ˜‘κ°™μ•„μ•Ό ν•œλ‹€κ³  ν–ˆλ‹€.
ν•˜μ§€λ§Œ SELECT ... FOR UPDATE μΏΌλ¦¬λ‚˜ SELECT ... LOCK IN SHARE MODE둜 μ‘°νšŒλ˜λŠ” 것은 κ²°κ³Όκ°€ λ‹€λ₯Ό 수 μžˆλ‹€.

SELECT FOR UPDATE 쿼리?
κ°€μž₯ λ¨Όμ € LOCK을 νšλ“ν•œ μ„Έμ…˜μ˜ κ²€μƒ‰λœ λ ˆμ½”λ“œλ“€μ΄ UPDATE 쿼리 ν›„ COMMIT 되기 μ΄μ „κΉŒμ§€ λ‹€λ₯Έ μ„Έμ…˜λ“€μ€ ν•΄λ‹Ή λ ˆμ½”λ“œλ“€μ„ μˆ˜μ •ν•˜μ§€ λͺ»ν•˜λ„둝 ν•˜λŠ” κΈ°λŠ₯

κ·Έ μ΄μœ λŠ” SELECT ... FOR UPDATE 쿼리의 경우 SELECT ν•˜λŠ” λ ˆμ½”λ“œμ— μ“°κΈ° μž κΈˆμ„ κ±Έμ–΄μ•Ό ν•˜λŠ”λ°, 언두 λ ˆμ½”λ“œμ—λŠ” μž κΈˆμ„ κ±Έ 수 μ—†κΈ° λ•Œλ¬Έμ΄λ‹€. λ”°λΌμ„œ, 언두 μ˜μ—­μ˜ λ³€κ²½ μ „ 데이터λ₯Ό κ°€μ Έμ˜€λŠ” 것이 μ•„λ‹Œ ν˜„μž¬ λ ˆμ½”λ“œμ˜ 값을 κ°€μ Έμ˜€κ²Œ λ˜λŠ” ν˜„μƒμ΄ λ°œμƒν•œλ‹€.



μ΄λ ‡κ²Œ λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œ μˆ˜ν–‰ν•œ λ³€κ²½ μž‘μ—…μ— μ˜ν•΄ λ ˆμ½”λ“œκ°€ λ³΄μ˜€λ‹€ μ•ˆ λ³΄μ˜€λ‹€ ν•˜λŠ” ν˜„μƒμ„ PHANTOM READ라고 ν•œλ‹€. 

 

βœ… InnoDB μŠ€ν† λ¦¬μ§€ μ—”μ§„μ—μ„œλ„ SELECT FOR UPDATE λ˜λŠ” SELECT FOR SHARE λ“± μž κΈˆμ„ λ™λ°˜ν•œ SELECT μΏΌλ¦¬μ—μ„œλŠ” PHANTOM READκ°€ λ°œμƒν•  수 μžˆμ§€λ§Œ, 이것은 μ˜ˆμ™Έμ μΈ 상황이닀. 일반적인 μƒν™©μ—μ„œλŠ” InnoDB μŠ€ν† λ¦¬μ§€ μ—”μ§„μ˜ REPEATABLE READ 격리 μˆ˜μ€€μ—μ„œλŠ” κ°­ 락과 λ„₯슀트 ν‚€ 락 덕뢄에 PHANTOM READκ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€κ³  ν•œλ‹€.

 

 

4. SERIALIZABLE

ν•΄λ‹Ή 격리 μˆ˜μ€€μ€ κ°€μž₯ λ‹¨μˆœν•˜λ©΄μ„œ λ™μ‹œμ— κ°€μž₯ μ—„κ²©ν•˜λ‹€. 그만큼 λ™μ‹œ 처리 μ„±λŠ₯도 λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ˜ 격리 μˆ˜μ€€λ³΄λ‹€ 많이 떨어진닀.

 

InnoDB ν…Œμ΄λΈ”μ—μ„œλŠ” 기본적으둜 μˆœμˆ˜ν•œ SELECT μž‘μ—…μ€ μ•„λ¬΄λŸ° λ ˆμ½”λ“œ μž κΈˆλ„ 없이 μ‹€ν–‰λœλ‹€. 
ν•˜μ§€λ§Œ νŠΈλžœμž­μ…˜ 격리 μˆ˜μ€€μ΄ SERIALIZABLE둜 μ„€μ •λ˜λ©΄ 읽기 μž‘μ—…λ„ 곡유 잠금(읽기 잠금)을 νšλ“ν•΄μ•Όλ§Œ ν•˜λ©°, λ™μ‹œμ— λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ€ κ·ΈλŸ¬ν•œ λ ˆμ½”λ“œλ₯Ό λ³€κ²½ν•˜μ§€ λͺ»ν•˜κ²Œ λœλ‹€. 

ν•œ νŠΈλžœμž­μ…˜μ—μ„œ 읽고 μ“°λŠ” λ ˆμ½”λ“œλ₯Ό λ‹€λ₯Έ νŠΈλžœμž­μ…˜μ—μ„œλŠ” μ ˆλŒ€ μ ‘κ·Όν•  수 μ—†λŠ” 것이닀.

 

SERIALIZABLE 격리 μˆ˜μ€€μ—μ„œλŠ” 일반적인 DBMSμ—μ„œ μΌμ–΄λ‚˜λŠ” PHANTOM READ λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

 

ν•˜μ§€λ§Œ InnoDBμ—μ„œλŠ” REPEATABLE READ 격리 μˆ˜μ€€μ—μ„œλ„ PHANTOM READκ°€ λ°œμƒν•˜μ§€ μ•ŠμœΌλ―€λ‘œ ꡳ이 SERIALIZABLE을 μ‚¬μš©ν•  ν•„μš”μ„±μ€ μ—†λ‹€