본문 바로가기

개발/DB

[DB]격리수준(Isolation Level)

실제 운영중인 시스템에서, 데이터베이스에 의도하지 않은 값이 들어가거나, 중간에 엉뚱한 Insert 또는 Update 쿼리로 인해 데드락이 발생하는 경우가 있었다.(심지어 Select 임에도 불구하고...)

왜 Select중에 교착상태가 발생하는 것일까...? 의문을 가지게 되면서 데이터베이스의 격리수준에 대해 공부하게 되었다.

 

데이터베이스의 격리 수준은 대표적으로 4가지로 나뉘어진다.(아래로 갈수록 격리 수준 ↑, 성능 ↓)

1. READ UNCOMMITTED

2. READ COMMITTED

3. REPEATABLE READ

4. SERIALIZABLE

 

하나씩 살펴보자면

1. READ UNCOMMITTED

  • Commit 되지 않은 데이터를 읽을 수 있다. 즉 하나의 트랜잭션에서 Insert나 Update 할 경우 Commit이 되지 않아도, 다른 트랜잭션에서 변경된 데이터를 읽을 수 있다는 의미이다.

2. READ COMMITTED

  • Commit 된 데이터만 읽을 수 있다. READ COMMITTED 에서는 Row가 Insert나 Update 상태라면, Select는 앞서 수행중인 트랙잭션이 Commit 될때까지 대기상태에 머무르게 된다. 물론 이 경우에도 다른 Row는 가져오는데에 문제가 없다.
  • Oracle의 default 설정

3. REPEATABLE READ

  • 반복읽기. 한 트랜잭션 내에서 읽었던 값은 변하지 않아야 한다. 즉, 트랜잭션 내에서 읽은 값은 다른 트랙잭션에서 변경조차 불가능하다는 것이다. 한 트랜잭션에서 Select 하게되면 S Lock이 걸리게 되고, 이 상태에서는 같은 S Lock을 공유하는 Select는 가능하나, Update나 Insert는 불가능하다.
  • 다만 이 경우에도 다른 Row는 잠기지 않으므로, Insert나 Update가 가능하다.
  • MySQL의 default 설정

4. SERIALIZABLE

  • 직렬화. 해당 격리수준은 인덱스와도 연관을 가진다. 인덱스가 있는 테이블일 경우 Select중인 Row뿐만 아니라 이전 행과 다음 행까지 잠그게 된다.
  • 물론 범위로 Select하게 될 경우에도 해당 범위의 이전행과 다음행까지 잠근다.
  • 하지만 SERIALIZABLE 에서 테이블에 인덱스가 없다면, 범위를 특정지을 수 없기 때문에 전 범위에 대한 잠금이 걸리게 된다.
  • SERIALIZABLE 격리수준은 가장 강력한 격리수준이지만, 성능저하가 발생할 수 있다.

 

*각 격리수준에 따라 파생되는 문제에 대해서는 다음 포스팅에 이어서 진행 예정...

 

더 자세한 설명과 예시는 아래를 참고할 것!

참고 : https://www.sqler.com/board_Column/365899