트랜잭션 격리 수준(Isolation Level)의 이해: 데이터 일관성과 성능의 균형
개요
Isolation level은 트랜잭션에서 일관성이 없는 데이터를 어느 수준까지 허용할 것인지 정의하는 데이터베이스의 중요한 개념입니다. 격리 수준이 낮을수록 여러 사용자가 동일한 데이터에 동시에 접근할 수 있어 성능이 향상되지만, 이로 인해 잘못된 데이터를 읽거나 데이터 업데이트가 손실되는 문제가 발생할 수 있습니다.
반대로 격리 수준이 높아질수록 데이터의 일관성은 보장되지만, 동시에 접근 가능한 사용자의 수가 줄어들어 성능이 저하될 수 있습니다. 이러한 균형을 맞추기 위해 대부분의 데이터베이스 시스템은 네 가지 격리 수준을 제공하며, 애플리케이션의 요구 사항에 따라 적절한 격리 수준을 선택할 수 있도록 설계되었습니다.
용어 설명
격리 수준을 이해하기 위해 먼저 Dirty Read, Non-repeatable Read, Phantom Read라는 개념을 알아야 합니다. 이는 각각 트랜잭션 간의 충돌로 인해 발생할 수 있는 대표적인 문제들입니다.
Dirty Read
커밋되지 않은 데이터를 다른 트랜잭션에서 읽는 것을 허용할 때 발생합니다. 이는 롤백된 데이터를 읽음으로써 잘못된 정보를 기반으로 동작하게 되는 문제를 초래합니다.
Transaction 1 | Transaction 2 |
---|---|
SELECT age FROM users WHERE id = 1; | |
UPDATE users SET age = 21 WHERE id = 1; | |
SELECT age FROM users WHERE id = 1; | |
ROLLBACK; |
위 예시에서 Transaction 1은 커밋되지 않은 데이터를 읽었기 때문에, 최종적으로 롤백된 값(21)을 잘못 참조하게 됩니다.
Non-repeatable Read
한 트랜잭션 내에서 동일한 쿼리를 두 번 수행했을 때, 그 사이에 다른 트랜잭션이 데이터를 수정하거나 삭제하여 첫 번째 조회와 두 번째 조회 결과가 달라지는 현상입니다.
Transaction 1 | Transaction 2 |
---|---|
SELECT age FROM users WHERE id = 1; | |
UPDATE users SET age = 21 WHERE id = 1; | |
COMMIT; | |
SELECT age FROM users WHERE id = 1; | |
COMMIT; |
위 예시에서 Transaction 1은 같은 데이터를 두 번 조회했지만, 중간에 Transaction 2가 데이터를 수정했기 때문에 결과가 일관되지 않습니다.
Phantom Read
한 트랜잭션 내에서 일정 범위의 레코드를 두 번 이상 읽었을 때, 첫 번째 쿼리에서는 없었던 새로운 레코드가 이후 쿼리에서 나타나는 현상을 말합니다. 이는 주로 레코드 삽입과 관련된 문제입니다.
Transaction 1 | Transaction 2 |
---|---|
SELECT age FROM users WHERE age < 20 | |
INSERT INTO users(name, age) VALUES ('홍길동', 10); | |
COMMIT; | |
SELECT age FROM users WHERE age < 20; | |
COMMIT; |
위 예시에서 Transaction 1은 처음에는 조건에 맞는 레코드가 없었지만, 중간에 Transaction 2가 새로운 레코드를 삽입하면서 결과가 달라집니다.
Isolation Level
데이터베이스는 위와 같은 문제를 해결하기 위해 네 가지 격리 수준을 제공합니다. 각 격리 수준은 허용되는 동시성 문제와 성능 간의 균형을 다르게 설정합니다.
Read Uncommitted
- 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용합니다.
- 가장 낮은 격리 수준으로, Dirty Read, Non-repeatable Read, Phantom Read 문제가 모두 발생할 수 있습니다.
- 성능은 가장 뛰어나지만 데이터 일관성이 낮습니다.
Read Committed
- 커밋된 데이터만 다른 트랜잭션이 읽는 것을 허용합니다.
- Dirty Read 문제는 방지하지만, 여전히 Non-repeatable Read와 Phantom Read 문제가 발생할 수 있습니다.
- 대부분의 DBMS가 기본 격리 수준으로 채택하고 있는 모드입니다.
Repeatable Read
- 한 트랜잭션이 읽은 데이터를 다른 트랜잭션이 수정하거나 삭제하지 못하도록 보장합니다.
- Non-repeatable Read 문제를 방지하며, 동일한 데이터를 여러 번 조회해도 항상 일관된 결과를 얻을 수 있습니다.
- 그러나 여전히 Phantom Read 문제가 발생할 가능성이 있습니다.
Serializable
- 가장 높은 격리 수준으로, 모든 트랜잭션을 직렬화하여 처리하는 것처럼 동작합니다.
- 선행 트랜잭션이 읽은 데이터에 대해 후행 트랜잭션이 수정, 삭제뿐만 아니라 새로운 레코드 삽입도 불가능하게 만듭니다.
- 완벽한 데이터 일관성을 보장하지만 성능 저하가 크며, 동시성 처리 능력이 크게 제한됩니다.
결론
Isolation level은 트랜잭션 간의 동시성과 데이터 일관성 사이에서 균형을 맞추기 위한 중요한 설정입니다. 애플리케이션의 요구 사항과 시스템 성능 목표에 따라 적절한 격리 수준을 선택하는 것이 중요합니다. 예를 들어, 금융 시스템처럼 높은 데이터 일관성이 요구되는 경우에는 Serializable 수준을 고려해볼 수 있으며, 반대로 높은 성능과 동시성이 중요한 경우에는 Read Committed나 Read Uncommitted를 선택할 수 있습니다.