로마
- 트랜잭션 ACID 성질 중에는 Isolation에 관한 내용이 있습니다. 둘 이상의 트랜잭션이 동시에 실행되고 있을 때 어떤 트랜잭션도 다른 트랜잭션 연산에 끼어들 수 없다는 내용입니다. 이를 가장 단순하게 지키는 방법은 순차적으로 트랜잭션 작업을 처리하는 것입니다. 하지만 이럴 시에는 동시성 성능이 매우 떨어지게 되므로 각 DBMS에서는 Isolation 성질을 트랜잭션 격리 수준을 이용해서 완화하여 적용하게 됩니다.
-
트랜잭션 격리 수준은 여러 클라이언트가 같은 데이터에 접근 할 때 경쟁 상태가 되는데 이 경쟁 상태를 어떻게 트랜잭션 접근을 제어할 지에 대한 설정을 의미합니다. 격리 수준으로는
Read Uncommitted,Read Committed,Repeatable Read,Serializable이 있습니다. -
먼저
Read Uncommitted는 커밋 전의 트랜잭션의 데이터 변경 내용을 다른 트랜잭션에서도 읽는 것을 허용하는 격리단계이다. 해당 단계에서는 두 트랜잭션 A,B가 존재할 때 A 트랜잭션에서 값을 바꾸고 이 값을 B 트랜잭션에서 사용하고 있는데 갑자기 A 트랜잭션이 롤백을 하게 되었을 때 생기는 데이터 정합성의 문제 즉, Dirty Read 문제가 발생할 우려가 있습니다. 또한 non-repeatable read, phantom read 문제도 발생하기 때문에 대부분의 DBMS에서 사용하지 않는 단계라고 볼 수 있습니다. -
두 번째 단계는
Read Committed입니다. 커밋 된 트랜잭션의 변경 사항만 읽을 수 있게 제한하는 격리수준을 의미합니다. 해당 단계의 격리 수준을 사용하게 되면 커밋 되지 않은 데이터를 읽을 때 발생할 수 있었던 Dirty Read 문제는 해결할 수 있지만 Non-repeatable read, phantom read 문제가 발생할 수 있습니다. non-repeatable read는 같은 데이터에 대해서 조회하는 쿼리를 날렸을 때 다른 트랜잭션의 커밋 시점에 따라 값이 다르게 조회되는 문제를 의미합니다. -
세 번째 단계는
Repeatable Read단계입니다. 해당 단계에서는 한 트랜잭션 범위 내에서는 다른 트랜잭션에서 데이터가 변경되더라도 조회한 데이터의 내용이 항상 동일함을 보장합니다. MySQL의 InnoDB 엔진에서는 해당 Repeatable Read를 디폴트로 사용하고 있습니다. Repeatable Read를 구현하기 위해서 MVCC와 같은 구현이 있습니다. MVCC는 Multi-Version Concurrency Control 의 약자로 읽는 시점에서 특정 버전에 해당하는 데이터를 읽게 하여 각 트랜잭션을 격리하는 방법입니다. 하지만 이 격리 단계에서도 Phantom Read 문제가 발생할 수 있습니다. Phantom read는 여러 레코드에 대한 조회를 할 시에 다른 트랜잭션에서 INSERT 혹은 DELETE를 할 때 여러 레코드에 대한 조회 결과가 달라질 수 있는 문제를 의미합니다. -
마지막 단계는
Serializable입니다.Serializable은 각 트랜잭션을 완전히 격리하여 한 트랜잭션에서 사용하는 데이터를 다른 트랜잭션에서 접근하지 못하도록 하는 방법입니다. 가장 독립성이 높지만 성능은 떨어지는 단계라고 볼 수 있습니다.
-
read-skew가 뭔가요?
- 읽는 시점에 데이터가 바뀌는 문제를 나타냅니다. 읽는 시점에 따라 데이터가 유효하거나 유효하지 않은지가 달라져 데이터가 깨지는 것을 의미합니다. Non-repeatable read와 비슷하다고 볼 수 있습니다.
-
Non-repeatable read 와 Phantom read의 차이점은 무엇인가요?
- non-repeatable read는 단일 레코드에 대한 조회 시에 다른 트랜잭션에서 해당 레코드의 데이터를 변경함에 따라 조회에 대한 결과가 달라지는 것을 의미합니다.
- phantom read는 단일 레코드가 아닌 두 개 이상의 레코드 조회 시에 다른 트랜잭션에서 레코드를 삽입, 삭제하는 경우에 레코드 조회 결과가 달라지는 것을 의미합니다.
-
오라클과 MySQL은 서로 default 격리 수준이 다른데요, 왜 두 벤더사는 다른 디폴트를 추구할까요?
- default 격리 수준이 다른 이유는 각 벤더에서 중요시하는 부분이 달라서 그런것 같습니다. 동시성 성능보다 데이터 정합성을 중요시한다면 Repeatable Read, Serializable과 같은 격리 수준을 사용할 것이고, 그보다 성능을 좀 더 중요시한다면 Read Committed와 같은 격리 수준을 사용하는 것과 같은 판단이 아니었을까 싶습니다. 또한, 대부분의 DBMS에서는 디폴트 외에 옵션으로 나머지 격리 레벨도 제공하기 때문에 디폴트 격리 수준이 마음에 들지 않는다면 다른 격리 레벨로 변경도 가능합니다.
MySQL 트랜잭션 Isolation Level로 인한 장애 사전 예방 법
프로그래밍 초식 : DB 트랜잭션 조금 이해하기 02 격리
[MySQL] - 트랜잭션의 격리 수준(Isolation level)
A beginner's guide to ACID and database transactions - Vlad Mihalcea


