HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🤩
개발
/데이터베이스(Database)/
Database
Database
/
🥎
ISOLATION(DB 고립수준)
🥎

ISOLATION(DB 고립수준)

[MySQL] MVCC(다중 버전 동시성 제어)와 데이터베이스가 트랜잭션을 지원하는 방법과 동작 과정
Multi Version Concurrency Control
IsolationREAD_UNCOMMITED(level 1)READ_COMMITED(level 2)REPETABLE_READ(level 3) - mysql 기본SERIALIZABLE(level 4)

Isolation

  • level이 올라갈수록 데이터 정합성이 더 보장이 되지만, 성능은 떨어질 수 있음. 동시성 저하. 일반적으로 READ_UNCOMMITED는 데이터 정합성 보장이 x, SERIALIZABLE은 성능 이슈가 있기에 그 사이 Isolation 단계를 많이 사용함
  • DEFAULT(lEVEL 0)

READ_UNCOMMITED(level 1)

다른 Transaction의 commit 되지 않은 데이터도 읽음 → dirty read
  • transaction 1 이 row를 update함
  • transaction 2 가 해당 row를 읽음(transaction 1이 커밋되기 전에)
  • transaction 1 이 롤백 시, transaction 2 는 존재하지도 않는 데이터를 읽게 됨
  • 현재 Transaction에서 update를 하려고 할 시 다른 Transaction이 commit이 될 때까지 lock이 걸리게 됨

READ_COMMITED(level 2)

커밋이 완료된 데이터만 다른 트랜잭션에서 조회 가능함 → Unrepetable Read 발생 가능
  • transaction 1 에서 row를 읽음
  • transaction 2 에서 row를 수정하고 커밋함
  • transaction 1 에서 row를 다시 읽음 → Unrepeatable read 발생 (transaction 2 에서 변경한 값을 읽게 됨)

REPETABLE_READ(level 3) - mysql 기본

InnoDB 스토리지 엔진에서는 트랜잭션이 Rollback 될 가능성에 대비해 변경되기 전 레코드를 Undo 영역에 백업해두고 실제 레코드 값을 변경함 ( MVCC — Multi Version Concurrency Control )
  • MVCC : DBMS에서 쓰기 세션이 읽기 세션을 블로킹하지 않고, 읽기 세션이 쓰기 세션을 블로킹하지 않게 서로 다른 세션이 동일한 데이터에 접근했을 때 각 세션마다 스냅샷 이미지 보장해주는 메커니즘
  • Undo 영역 : UPDATE, DELETE 로 인해 데이터 변경 시, 변경되기 전의 데이터를 보관하는 곳 (롤백 대비용, 격리 수준 유지용)
  • 트랜잭션 별로 Undo 영역에 백업 데이터를 만들어 두기 때문에(Snapshot) 동시에 여러 Transaction 이 진행되어 백업 레코드가 많아질수록 MySQL 서버 처리성능 떨어질 수 있음
  • Transaction이 시작할 때 snapshot을 가지고 있고 거기서 부터 값을 읽음
    • 기존에 존재하는 데이터는 Undo 영역에 존재할 수 있지만 새로 추가된 데이터는 Undo 영역에 존재할 수가 없음 ⇒ Undo 영역의 snapshot을 가지고 시작하여도, 새로 추가된 데이터에 대해서는 조회가 되는 것임 (Phantom Read) — 추측
Phantom Read
  • transaction 1 에서 특정 기준을 충족하는 row를 조회
    • SELECT … FOR UPDATE 쿼리는 SELECT 하는 레코드에 쓰기 잠금을 적용해야 하는데, Undo 레코드에는 잠금을 걸 수 없으므로, 현재 레코드의 값을 가져오게 됨
  • transaction 2 에서 해당 기준을 충족하는 row를 추가
  • transaction 1 에서 동일한 기준으로 row 조회 시, row 개수가 달라짐
@Modifying @Query(value= "update book set category='update'", nativeQuery=true) // repository로 update시에는 // select 후 update를 하기에 phantom read 현상 나타내기 힘들어서 nativeQuery사용 void update();

SERIALIZABLE(level 4)

  • 다른쪽에서 데이터를 수정하는 Transaction이 시작되면 현재 Transaction은 그냥 걔가 끝날 때까지 무조건 기다림(락이 걸림)