트랜잭션 격리수준(Isolation Level) 이란?

  • 동시에 여러 트랜잭션이 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회할 수 있도록 허용하는 레벨
  • 격리수준
    • Read Uncommitted
    • Read Committed
    • Repeatable Read
    • Serializable
  • 격리 수준이 높아질수록 동시성은 떨어진다.

격리 수준(Isolation Level)

Read Uncommitted

  • 일반적으로 거의 사용하지 않는다.
  • 어떤 트랜잭션이 처리한 작업이 완료되지 않았는데도 다른 트랜잭션에서 테이블 볼 수 있다.
  • commit/rollback 여부에 상관 없이 다른 트랜잭션의 변경/조회 허용
  • Dirty ready, Non-repeatable read, Phantom read 현상 발생

Read Committed

  • 오라클 DBMS에서 기본적으로 사용되는 격리수준(Shared Lock 사용)
  • 데이터를 변경했더라도 commit이 완료된 데이터만 다른 트랜잭션에서 조회 가능
  • 어떤 트랜잭션에서 처리한 작업이 commit이 안되어 있다면 다른 트랜잭션은 undo 영역에 있는 기존 값을 참고하여 보여 주게 된다.
  • Non-Repeatable Read 문제 발생
    • 하나의 트랜잭션 내에서 동일 select쿼리를 실행했을 때는 항상 같은 결과를 가져와야 한다는 정합성 정의(select한 후 잠깐 사이에 데이터 insert or update가 일어 났는데도, 동일 select결과가 나오는 것)
    • 돈을 인출하는 과정에서 돈이 있어서 인출하려는 사이에 금액의 변경이(자동이체) 생겼는데 그대로 select되서 인출이 가능한 상황 발생

Repeatable Read

image.png

  • MySQL InnoDB에 기본적으로 사용되는 격리 수준(모든 데이터에 shared lock이 걸리므로 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정 불가)
    • MySQL에서는 트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경한 것만 읽게 된다.
    • 트랜잭션1(id : 12)가 테이블 업데이트를 해서 commit되기 전까지 , 트랜잭션2(id:10)은 자신보다 높은 트랜잭션이 변경한 테이블을 읽어오지 않고, undo영역에서 백업된 데이터를 읽어와서 부정합성문제 해결
  • Non-Repeatable Read 부정합이 발생하지 않음
  • InnoDB Storage Enging은 트랜잭션이 Rollback될 가능성에 대비해 변경되기 전 레코드를 Undo 공간에 백업해 두고 실제 레코드 값을 변경(MVCC - Multi Version Concurrency Control)
  • MVCC를 위해 undo 영역에 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서는 동일한 결과를 보여줄 수 있도록 보장
  • read commit와의 차이는 undo 영역에 백업된 레코드의 버전 가운데 몇 번째 이전 버전까지 찾아 들어가야 하는지에 있음
  • select for update query의 경우 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안보였다가 할 수 있다. (phantom row, undo 영역을 lock 할 수 없기 때문에 변경 전 데이터가 아닌 현재 변경된 레코드를 표현)
    • 위의 그림에서, 트랜잭션1 commit전까지는 김춘수였다가, commit이 완료된 후에는 이순신이된다.

Serializable

  • 동시성이 중요한 DB에서는 거의 사용 x
  • 읽기 작업도 공유 잠금을 획득해야 한다.
  • 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근할 수 없다.
  • Phantom Read문제가 발생하지 않지만, inno db 스토리지 엔진에서는 repeatable read격리 수준에서도 이미 phantom read가 발생하지 않아서 굳이 serializable 사용할 필요 없다.

정리

  • MVCC(Multi Version Concurrency Control) : 잠금을 사용하지 않는 일관된 읽기를 제공하는 것이 목적
  • Read Uncommitted : 변경되었거나 안된 데이터의 값을 읽음
  • Read Committed : 변경 전 Undo 에 있는 값을 읽음
  • Repetable Read가 트랜잭션을 열어 해당 트랜잭션에서 모든 테이블의 데이터를 select한 후 그대로 두면 innoDB의 undo 영역이 계속 커져서 시스템 테이블스페이스 I/O가 유발(성능 저하)
    • 해당 문제를 일으키지 않으면 성능상 차이가 거의 없다.
    • Binary Log가 활성화된 mysql server에서는 read committed 격리 수준을 사용할 수 없다.

MySQL에서 트랜잭션 격리수준 확인

show variables like 'tx_isolation';