트랜잭션은 ACID의 특징을 갖는다. 이러한 ACID는 항상 엄격하게 지켜지는 것은 아니다. 엄격하게 ACID를 지키려고 노력하면 동시성이 떨어져 성능이 나빠진다.
우리는 적절한 Isolation Level을 선택하여 안정성과 동시성 사이의 트레이드오프를 현명하게 해야한다.
그러기 위해서 우리는 Isolation Level과 DB 동시성 제어를 위해 사용되는 Lock에 대해 학습해야한다.
Dirty Read는 아직 커밋되지 않은 데이터를 읽어서 발생하는 문제이다.
여기서 TransactionA가 커밋되지 않고 롤백되면 TransactionB는 잘못된 데이터를 참조하여 작업되므로 데이터 무결성이 깨지게 된다.
한 트랜잭션 내에서 동일한 조건의 조회 쿼리가 다른 결과를 반환하는 현상을 말한다.
한 트랜잭션 내에서 동일한 Row의 검색 결과가 다른 결과를 반환하는 문제이다.
Phantom Read와 Non-Repeatable Read의 차이
Phantom Read는 조건 절을 통해 검색한 결과(여러개가 될 수 있음)가 변경될 수 있는 문제를 의미하고 Non-Repeatable Read는 단일 Row의 결과가 바뀔 수 있는 문제를 말한다.
Serializable은 가장 엄격한 수준의 독립성을 제공하여 데이터 정합성을 보장합니다.
SELECT 쿼리가 실행될 때마다, 해당 데이터에 대해 락이 걸리며 동일 트랜잭션 내에서 해당 데이터를 갱신(UPDATE, INSERT, DELETE)할 수 없게 됩니다.
Serializable은 높은 데이터 정합성을 갖는다는 장점이 있지만 동시성 수준을 많이 떨어뜨리기 때문에 정합성이 반드시 필요한 프로젝트에서만 제한적으로 사용되어야 합니다.
Repeatable Read는 동일 트랜잭션 내에서 반복적인 읽기(SELECT)의 정합성을 보장해주는 Isolation Level입니다.
A 트랜잭션이 수행 중에 B 트랜잭션이 쓰기 작업을 수행하고 커밋이 되더라도 A 트랜잭션의 조회 결과에 B 트랜잭션의 결과가 간섭할 수 없습니다.
이는 MySQL의 각 커밋 결과에 대한 스냅샷을 저장하고 있기 때문에 가능하다. A 트랜잭션은 이전의 커밋된 결과에 대한 스냅샷만을 참조하므로 B 트랜잭션의 커밋된 결과에 대해 접근하지 못한다.
Read Commited 수준에서는 커밋된 데이터에는 접근이 가능하도록 합니다.
따라서 Phantom Read와 Non-Repeatable Read 문제가 발생할 수 있습니다.
Read Uncommited는 커밋되지 않은 데이터에 접근이 가능합니다. 따라서 다른 트랜잭션이 데이터베이스에 수행한 쓰기 연산의 결과를 트랜잭션 내에서 조회할 수 있습니다.
따라서 Phantom Read, Non-Repeatable Read, Dirty Read 문제가 발생합니다.
어떤 제품을 만드는지에 따라 적절한 Isolation Level을 선택하여 동시성과 데이터 정합성 사이의 트레이드오프를 현명하게 해야한다.
각 Isolation Level 마다 발생할 수 있는 문제에 대해 정확하게 인식하여 예기치 않은 문제가 발생하지 않도록 하자.