NoTimeForDawdling

트랜잭션 격리 수준(Isolation Level) 본문

DB

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

Room_Energy 2021. 2. 18. 15:25

트랜잭션 격리 수준이란?

  • 트랜잭션 격리 수준이란 동시에 여러 트랜잭션이 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지 결하는 것입니다.
  • 즉, 특정 트랜잭션이 다른 트랜잭션에 select, insert, update, delete를 허용할지 말지 결정하는 것입니다.

트랜잭션 격리 수준은 크게 4가지로 나뉩니다.

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

4개의 격리 수준에서 순서대로 뒤로 갈수록 각 트랜잭션 간의 데이터 격리(고립) 정도가 높아지며, 동시성은 떨어집니다.(성능 저하)

 

일반적인 온라인 서비스에서는 READ COMMITTED와 REPEATABLE READ 둘 중 하나를 많이 사용합니다.

READ UNCOMMITTED은 데이터 정합성의 문제가 많아 잘 사용하지 않습니다.

SERIALIZABLE은 동시성이 중요한 데이터베이스에서 거의 사용하지 않습니다.

각각의 격리 수준에 따라 발생할 수 있는 3가지 부정합 문제

1. Dirty Read

  • Dirty Read는 트랜잭션 T1에서 A=1001로 update 하고 아직 commit하지 않았는데 다른 트랜잭션 T2가 commit하지 않은 A의 값을 읽을 수 있도록 허용하는 경우 발생합니다.
  • 즉, 트랜잭션 T1이 특정 데이터를 update를 수행한 후 commit을 하지 않았는데 다른 트랜잭션(T2)이 commit하지 않은 값을 조회할 수 있는 경우를 뜻합니다.
  • Dirty Read는 데이터가 나타났다가 사라졌다 하는 현상을 초래하므로 개발자와 사용자에게 굉장히 혼란스러울 수 있습니다.

2. Non Repeatable Read

  • Non Repeatable Read는 트랜잭션 T1이 같은 쿼리를 두 번 실행했는데 그 결과값이 다른 경우를 말합니다.
  • 즉, 트랜잭션 T1이 select을 두 번 하는 사이에 다른 트랜잭션(T2)이 update나 delete를 한 경우를 뜻합니다.

3. Phantom Read

  • 트랜잭션 T1이 같은 쿼리를 두 번 수행 시 첫 번째 실행 시에 없던 레코드가 두 번째 실행시에 튀어나오는 경우를 말합니다.

위의 3가지 문제점을 각각의 트랜잭션 격리 수준과 함께 알아보겠습니다.

4가지 격리 수준

1. READ UNCOMMITTED

  • READ UNCOMMITTED 격리 수준은 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관없이 다른 트랜잭션에 보입니다.
  • 즉, 트랜잭션 T1이 아직 commit하지 않은 데이터를 다른 트랜잭션 T2가 조회하는 것을 허용합니다.
  • 이렇게 특정 트랜잭션이 처리한 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있게 되는 Dirty Read 현상이 발생합니다.
  • Dirty Read를 유발하는 READ UNCOMMITTED는 트랜잭션의 격리 수준으로 인정하지 않을 정도로 정합성에 문제가 많습니다.

2. READ COMMITTED

  • READ COMMITTED 격리 수준은 트랜잭션 T1이 commit 한 데이터만 다른 트랜잭션 T2가 조회하는 것을 허용합니다.
  • 즉, 특정 트랜잭션에서 변경한 데이터를 commit이 완료된 후에 다른 트랜잭션에서 조회할 수 있기 때문에 Dirty Read와 같은 현상은 발생하지 않습니다.
  • 특정 트랜잭션(T1)이 update 하기 전 값은 Undo 영역으로 백업됩니다. 다른 트랜잭션이 같은 값을 조회할 때 Undo 영역에 있는 값을 조회하기 때문에 변경한 내용이 commit 되지 전까지는 변경 내역을 조회할 수 없게 됩니다.
  • READ COMMITTED 격리 수준에서는 Non Repeatable Read 현상이 발생합니다.
  • 예를 들어, 트랜잭션 T1에서 first_name이 'Toto'인 데이터를 검색했는데 일치하는 결과가 없습니다. 하지만 다른 트랜잭션 T2가 A라는 사원 이름을 'Toto'로 변경하고 commit을 실행한 이후, 트랜잭션 T1이 똑같은 SELECT 쿼리로 다시 조회하면 1건의 데이터가 나타납니다.
  • 이렇게 하나의 트랜잭션 내에서 똑같은 SELECT 쿼리를 실행했을 때 항상 같은 결과를 가져오지 못하게 되는 Non Repeatable Read 현상이 발생합니다.
  • READ COMMITTED 격리 수준은 오라클과 같은 DBMS에서 주로 사용됩니다.

3. REPEATABLE READ

  • REPEATABLE READ는 선행 트랜잭션 T1이 읽은 데이터는 T1이 종료될 때까지 다른 트랜잭션이 udpate&delete를 허용하지 않습니다. 단 insert은 허용합니다.
  • REPEATABLE READ는 Undo 영역에 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서는 동일한 결과를 보여줄 수 있도록 보장합니다.
  • 예를 들어, 10번 트랜잭션 안에서 실행되는 모든 SELECT 쿼리는 트랜잭션 번호가 10(자신의 트랜잭션 번호) 보다 작은 트랜잭션 번호에서 변경한 것만 보게 됩니다. 그렇기 때문에 Non Repeatable Read 현상은 발생하지 않습니다.
  • Undo 영역에 백업된 모든 레코드는 변경을 발생시킨 트랜잭션 번호가 포함돼 있습니다. REPEATABLE READ 격리 수준에서는 실행 중인 트랜잭션 가운데 가장 오래된 트랜잭션 번호보다 트랜잭션 번호가 앞선 Undo 영역의 데이터는 삭제할 수 없습니다.
  • REPEATABLE READ 격리 수준에서는 Phantom Read 현상이 발생합니다.
  • REPEATABLE READ 격리 수준은 MySQL에서 주로 사용합니다.

4. SERIALIZABLE

  • SEREALIZABLE은 선행 트랜잭션 T1이 읽은 데이터는 T1이 종료될 때까지 다른 트랜잭션이 update&delete&insert 전부 불가능합니다.
  • 격리 수준이 엄격한 만큼 동시 처리 성능도 다른 트랜잭션 격리 수준보다 훨씬 떨어집니다.

 

'DB' 카테고리의 다른 글

DB 데이터 캐싱(Caching)  (0) 2021.03.11
ORM(Object Relation Mapping)이란?  (0) 2021.03.10
DB 인덱스(Index)  (0) 2021.03.04
Primary Key vs Unique Key  (0) 2021.02.26
트랜잭션(Transaction)  (0) 2021.02.16