트랜잭션의 격리 수준(isolation level)이란?
- 동시에 여러 트랜잭션이 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회한 데이터를 볼 수 있도록 허용 여부를 결정하는 것
트랜잭션 격리 수준의 필요성
- 데이터베이스는 ACID 같이 트랜잭션이 원자적이면서도 독립적인 수행을 하도록 한다.
- 트랜잭션이 DB를 다루는 동안 다른 트랜잭션이 관여하지 못하게 막는 Locking 이라는 개념이 등장한다.
- 무조건적인 Locking 으로 동시에 수행되는 많은 트랜잭션들을 순서대로 처리할 시에 DB 성능은 떨어지게 된다.
- 반대로, 응답성을 높이기 위해 Locking 범위를 줄인다면 잘못된 값이 처리 될 여지가 있다.
- 최대한 효율적인 Locking 방법이 필요하다.
트랜잭션 격리 수준의 종류
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SELIALIZABLE
READ UNCOMMITTED (Level 0)
- 각 트랜잭션의 변경 내용이 COMMIT / ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 값을 읽을 수 있다.
- 정합성에 문제가 많은 격리 수준이기 때문에 사용하지 않는 것을 권장한다.
- 아래 그림과 같이 COMMIT 되지 않은 상태지만, UPDATE 된 값을 다른 트랜잭션에서 읽을 수 있다.
READ COMMITTED (Level 1)
- 대부분의 RDB 에서 기본적으로 사용되고 있는 격리 수준이다.
- Dirty Read 와 같은 현상은 발생하지 않는다.
- 실제 테이블 값을 가져오는 것이 아니라, Undo 영역의 백업된 레코드에서 값을 가져온다.
- 하나의 트랜잭션에서 똑같은 SELECT 쿼리를 실행 하였을 때 항상 같은 결과를 가져와야하는 REPEATABLE READ 의 정합성에 어긋난다.
REPEATABLE READ (Level 2)
- MySQL 경우 트랜잭션마다 트랜잭션 ID 를 부여하여 해당 ID 보다 작은 트랜잭션 번호에서 변경한 것만 읽게 된다.
- Undo 공간에 백업해두고 실제 레코드 값을 변경한다.
- 백업된 데이터는 불필요하다고 판단하는 시점에 주기적으로 삭제한다.
- Undo 에 백업된 레코드가 많아지면, MySQL 서버의 처리 성능이 떨어질 수 있다.
- 이러한 변경 방식을 MVCC(Multi Version Concurrency Control) 라고 부른다.
SERIALIZABLE (Level 3)
- 가장 단순한 격리 수준이지만 가장 엄격한 격리 수준이다.
- 성능 측면에서는 동시 처리 성능이 가장 낮다.
- SERIALIZABLE 에서는 PHANTOM READ 가 발새하지 않는다. 하지만, DB 에서 거의 사용되지 않는다.
낮은 단계의 트랜잭션 격리 수준 이용 시에 발생하는 현상
Dirty Read
- 트랜잭션 작업이 완료되지 않았는데, 다른 트랜잭션에서 볼 수 있게 되는 현상
Non-Repeatable Read
- 한 트랜잭션에서 같은 쿼리를 두 번 수행할 때, 두 쿼리의 결과가 상이하게 나타나는 비일관성 현상
- 한 트랜잭션이 수행 중일 때 다른 트랜잭션이 값을 수정 또는 삭제함으로써 나타난다.
Phantom Read
- 한 트랜잭션에서 같은 쿼리를 두 번 수행할 때, 첫 번째 쿼리에서 없던 레코드가 두 번째 쿼리에서 나타나는 현상
- 한 트랜잭션이 수해 중일 때 다른 트랜잭션이 새로운 레코드를 INSERT 함으로써 나타난다.
RDB(MySQL, Oracle) 기본 Isolation Level
- MySQL : REPEATABLE READ
- ORACLE : READ COMMITTED
Oracle 은 READ COMMITTED 와 SERIALIZABLE 만 지원하며, 나머지 두가지 Isolation level 은 지원하지 않는다.
참고
https://nesoy.github.io/articles/2019-05/Database-Transaction-isolation