1. DB 데드락 (Deadlock)
데드락이란 두 개 이상의 트랜잭션이 서로 상대방이 갖고 있는 자원을 기다리며 무한히 대기하는 상황을 말한다.
예시
- 트랜잭션 A는 테이블 1에 대한 락을 얻고, 동시에 테이블 2에 대한 락을 요청한다.
- 트랜잭션 B는 테이블 2에 대한 락을 얻고, 동시에 테이블 1에 대한 락을 요청한다.
이 경우 트랜잭션 A는 트랜잭션 B가 가진 테이블 2 락을 기다리고, 트랜잭션 B는 트랜잭션 A가 가진 테이블 1 락을 가지게 된다. 결국 두 트랜잭션은 서로 상대방의 락을 기다리면서 진행되지 않으며, 데드락 상태에 빠진다.
해결 방법:
- 타임아웃 설정 : 일정 시간이 지나면 자동으로 트랜잭션을 취소하고, 해당 트랜잭션을 롤백하여 데드락을 해결할 수 있다.
- 데드락 탐지 : 데이터베이스는 주기적으로 데드락 상태를 검사하고, 이를 감지하면 트랜잭션을 강제로 롤백한다.
- 트랜잭션 설계 개선 : 락을 순차적으로 획득하는 방식으로 트랜잭션을 설계하여 데드락을 방지할 수 있다.
2. 트랜잭션 격리 레벨 (Transaction Isolation Levels)
트랜잭션 격리 레벨은 데이터베이스에서 여러 트랜잭션이 동시에 실행될 때, 한 트랜잭션 다른 트랜잭션에 의해 영향을 받지 않도록 보장하는 정도를 설정하는 것이다. 트랜잭션 격리 수준은 크게 4가지로 나뉜다.
1. READ UNCOMMITTED (가장 낮은 격리 레벨)
- 다른 트랜잭션이 아직 커밋하지 않은 데이터를 읽을 수 있다.
- 문제점 : "더티 리드"가 발생할 수 있다. 이는 다른 트랜잭션이 아직 커밋하지 않은 데이터를 읽는 상황으로, 데이터가 잘못된 상태일 수 있다.
2. READ COMMITTED
- 다른 트랜잭션이 커밋한 데이터만 읽을 수 있다.
- 문제점 : "비반복적 읽기"가 발생할 수 있다. 한 트랜잭션 내에서 동일한 쿼리를 두 번 실행했을 때 결과가 달라질 수 있다. 예를 들어, 다른 트랜잭션이 데이터를 수정하고 커밋했기 때문에, 두 번째 조회에서 다른 값이 반환될 수 있다.
3. REPEATABLE READ
- 한 트랜잭션 내에서 읽은 데이터는 다른 트랜잭션이 수정할 수 없다. 즉, 같은 데이터를 여러 번 읽을 때 같은 결과가 보장된다.
- 문제점 : "팬텀 리드"가 발생할 수 있다. 트랜잭션이 데이터를 읽을 때, 다른 트랜잭션이 새로운 데이터를 추가하는 경우, 첫번째 트랜잭션에서 두번째 조회 시 새로운 데이터가 포함될 수 있다.
4. SERIALIZABLE (가장 높은 격리 레벨)
- 모든 트랜잭션이 직렬화된 방식으로 처리되어, 하나의 트랜잭션이 완료될 때까지 다른 트랜잭션이 실행되지 않는다.
- 장점 : 완벽하게 동시성 문제가 해결된다.
- 단점 : 성능이 저하된다. 동시에 실행되는 트랜잭션이 많을 경우 처리 속도가 느려질 수 있다.
3. 트랜잭션 락 (Transaction Locks)
트랜잭션 락은 데이터베이스에서 여러 트랜잭션이 동시에 같은 데이터를 변경하지 않도록 보호하는 매커니즘이다. 락은 데이터가 동시성을 처리할 수 있게 하며, 동시에 여러 트랜잭션이 동일한 데이터를 수정하려고 할 때 충돌을 방지한다.
락 종류
공유 락 (Shared Lock)
- 데이터를 읽을 수는 있지만, 다른 트랜잭션이 해당 데이터를 수정할 수 없도록 한다.여러 트랜잭션이 데이터를 동시에 읽을 수는 있지만, 수정은 불가능하다.
배타적 락 (Exclusive Lock)
- 데이터를 읽고 수정할 수 있으며, 다른 트랜잭션은 이 데이터를 읽거나 수정할 수 없다. 트랜잭션이 완료될 때까지 해당 자원에 대한 모든 접근이 차단된다.
낙관적 락 (Optimistic Locking)
- 데이터를 읽은 후, 트랜잭션을 커밋할 때 다른 트랜잭션이 데이터를 수정하지 않았는지 확인한다. 만약 수정이 있었다면, 충돌을 해결하고 다시 시도할 수 있다.
- 주로 version 컬럼을 사용하여 트랜잭션 충돌을 관리한다.
정리
- "데드락"은 두 트랜잭션이 서로 상대방의 락을 기다리며 무한히 대기하는 상태를 의미한다. 이를 해결하려면 타임아웃 설정이나 데드락 탐지 기능을 활용해야 한다.
- "트랜잭션 격리 레벨"은 여러 트랜잭션이 동시에 실행될 때 데이터 일관성을 유지하는 방법을 정의한다. 높은 격리 레벨일수록 성능이 저하될 수 있지만, 더 강한 일관성을 제공한다.
- "트랜잭션 락"은 트랜잭션 간 충돌을 방지하기 위한 방법이다. 락을 적절히 관리하지 않으면 성능 문제가 발생할 수 있다.
보통의 트랜잭션 격리 레벨은 "READ COMMITTED"로 설정하는 경우가 많다. 이는 대부분의 데이터베이스에서 기본값으로 설정되는 격리 레벨이기도 하며, 일반적으로 적절한 성능과 데이터 일관성의 균형을 맞추기 때문이다.