본문 바로가기

DAP/06.데이터베이스 설계와 이용

[데이터베이스 설계와 이용] Locking 을 이용한 읽기 일관성 문제 (328)

Q : 읽기 일관성을 유지하기 위해서 Locking을 사용하지만 지나치게 Locking을 강화하면 작업의 동시성이 떨어지게 된다.
다음중 Locking을 통해서 읽기 일관성이 보장되지 않을 경우에 발생할 수 있는 문제점에 대한 설명으로 틀린것은?


1. 문장 수준의 읽기 일관성이 보장되지 않을경우, 트랜잭션 A(잔액 = 잔액 + 1000)와 트랜잭션 B(잔액 = 잔액 + 2000)가 동시에 잔액을 읽어 들인 후 수행하게 되면 잔액이 11,000원 혹은 12,000원이 되는데 이를 Lost Update라고 한다.

2. 아직 커밋되지 않고 수정중인 데이터에 대해 '읽기' 를 허용할 경우, 어떤 원인에 의해 수정사항이 롤백 된다면 '데이터 읽기' 트랜잭션은 잘못된 수행 결과를 초래하게 되는데 이러한 현상을 'Dirty Read'라고 한다.

3. DBMS가 단일 문장에 대한 읽기 일관성은 보장하지만, 트랜잭션 내에서 한개 이상의 문장이 반복 수행될 때 읽기 일관성을 보장하지 않는다면, 한 트랜잭션 내에서 같은 행을 두번 이상 읽는 사이에 다른 트랜잭션이 그 행을 변경할 경우에는 일관성이 깨어지는데 이를 Non - Repeatable Read라고 한다.

4. 한 트랜잭션 안에서 일정 범위의 레코드들을 두 번 이상 읽을 때, 이전 쿼리에 없던 레코드가 튀어 나오는 경우가 있는데 이러한 현상을 Phantom Read라고 한다. 이것은 select 작업을 할 때 설정한 공유잠김을 트랜잭션 종료시 까지 유지하면 해결할 수 있다.


해설 ) 

Lost Update : 선행 트랜잭션이 수정하고 잇는 데이터를, 후행 트랜잭션이 수정해 버리는 것을 말한다. 이것은 트랜잭션의 특징인 (ACID)중 고립성(Isolation)을 위반할 경우 발생하는 현상으로 실제 DBMS에서는 지원하지 않는다.

4. Phantom Read는 Isolation Level을 3단계로 변경하면 가능하며, select 작업할때 설정한 공유잠금 (select ~ for update)를 이용하더라도 phantom read를 막을 수 는 없다. [왜냐하면, row lock (select ~ for update)을 걸어도 해당 테이블에는 내용을 입력할 수 있기 때문이다.]. 그러므로 틀린 문장이 된다. 


# 기본지식 #                                       (http://wiki.oracleclub.com/pages/viewpage.action?pageId=3900116) 참조
1. 트랜잭션 수준의 읽기 일관성과 문장 수준의 읽기 일관성
2. 트랜잭션 고립화 수준
3. Dirty Read
4. Non-Repeatable Read 
5. Phantom Read


# 용어 설명 #
1.1 트랜잭션 수준의 읽기 일관성 :
- 트랜잭션이 시작되는 시점을 기준으로 일관성 있게 데이터를 읽어 들이는것

1.2 문장수준의 읽기 일관성 :
- 단일 SQL 문이 수행되는 도중에 다른 트랜잭션에 의해서 데이터의 추가, 변경, 삭제가 발생하더라도 일관성있는 결과집합을 반환하는것
- 해결방법 : Row Lock을 걸어서 해당 로가 Dirty Read를 방지. 읽기 작업에 대해서는 Shared Lock을 사용함으로 써, Exclusive Lock이 걸린 로를 읽지 못하도록 한다.


2. 트랜잭션 고립화 수준 (Transaction Isolation Level)
A. Level 0 : (Read Uncommitted)
- 트랜잭션에서 처리중인 데이터 즉, 아직 커밋되지 않은 데이터를 읽도록 허용하는것
- Dirty Read, Non-Repeatable, Phantom Read 현상 발생
- 사실상 트랜잭션에 대한 의미가 거의 없는 수준이 됨

B.  Level 1 : (Read Committed)
- Dirty Read 방지, 트랜잭션이 커밋된 데이터만을 읽어 들임
- 대부분의 DB에서 기본적으로 설정되어 있는 레벨
- Non-Repeatable Read, Phantom Read 현상은 여전히 발생

C. Level 2 : (Repeatable Read)
- 선행 트랜잭션이 읽은 데이터를 타 트랜잭션에서 읽는 것은 가능하나, 수정이나, 삭제는 불가능 하도록 하는것,
- 선행 트랜잭션이 끝이나면, 다음 트랜잭션에서는 이를 수정이나 삭제 가능
- 보통 오라클에서는 select ~ for update 구문을 이용하여 읽고, Row Lock을 걸어서 해당 로를 보호한다.
- 기타 DB에서는 고립화 수준을 Level 2로 변경해야지만 적용 가능
- Phantom read현상은 여전히 발생

D. Level 3 : (Serializable Read)
- 선행 트랜잭션이 읽은 데이터를 타 트랜잭션이 수정, 삭제가 불가능 하며, 해당 테이블에 삽입하는것 까지 불가능 하게 함
- 완벽한 읽기 일관성을 제공
- 동시성이 매우 떨어짐
- Phantom read 가 없어짐

3. Dirty Read (Uncommited Dependency)
- 수정 중인 데이터를 다른 트랜잭션이 읽을 수 있도록 할때 발생
- 대부분의 DB에서는 이러한 현상이 발생하지 않음 (대부분의 DBMS는 Isolation Level 1을 설정하고 있음)
- 갱신중인 데이터는 exclusive lock이 걸림 (즉, 수정중인 데이터는 읽지 못함) - 기타 DBMS 에는 Lock을 이용
- Oracle에서는 이러한 락을 사용하지 않고, 다중버전 읽기 일관성 채택함

4. Non-Repeatable Read (Inconsistent Analysis)
- 한 트랜잭션 내에서 같은 쿼리를 두번 수행할때, 다른 트랜잭션이 값을 수정함으로 해서 두 쿼리가 서로 다르게 나타나는 현상
- select ~ for update를 해서 처리하고자 하는 내용에 lock을 걸어서 이를 해결

5. Phantom Read
- 한 트랜잭션 안에서 일정 범위의 레코드를 2번 읽을때, 그사이 다른 트랜잭션이 범위 사이에 값을 입력하면, 첫번째 트랜잭션에서 값을 다시 읽을때 없던 데이터가 나타나는 현상
- 트랜잭션 도중 새로운 로가 입력될 수 있도록 허용할경우 발생
- 고립수준을 3으로 올리면 해결이 되나, 나머지 트랜잭션은 트랜잭션이 끝날때 까지 대기해야함
- 보통 Phantom Read는 업무상으로 서로 이해하에서 허용하도록 함으로써 문제를 피해가는것이 정석이다.