(우리는 앞의 두개만 살펴볼 것!)
직렬 가능성을 보장하기 위해 락(장금)을 사용하여 데이터 항목에 연산 작용 전 트랜잭션이 락을 획득하고 연산 후 반납하도록 하는 규약
지금 이거 내가 찜뽕햇으니까, 아무도 쓰지마!!!!!!! =락
락의 종류
트랜잭션은 연산하고자 하는 데이터에 대한 락을 획득해야만 연산 진행 가능
반드시 선 락을 걸고 후처리 한다
락 양립성 함수
공유락은 무조건 같이 사용 가능. 배타락은 무조건 같이 사용 불가능.
이미 락이 걸린 경우에는, 무조건 락이 끝날때까지 대기.
T10은 계좌 B에서 A로 천원을 이체하는 트랜잭션.
Write(B)를 위해 LX(B) 배타락을 미리 걸어놓음.
T11은 두 계좌의 값을 읽어서 출력하는 트랜잭션.
write없이 Read작업만 있어 LS(A) 공유락만 걸어 놓음.
이 두 트랜잭션이 동시에 요청되면 어떤 현상이 일어날까?
B에는 2만원, A에는 1만원이 있는 상황. 일련의 연산이 수행진다.
락을 정상적으로 사용했음에도 불구하고, T10의 계좌요청 사이에 T11이 끼어들어 일관성이 훼손된다.
T10이 락을 일찍 반납하여 비일관적인 상태에서 데이터 접근이 가능해저 T11이 정확하지 않은 결과값을 출력
이전 버전
일찍 안하고 락을 늦게 반납하면 되지 않을까?
이전과 달리 락 반납을 지연시켰다. 쓰고나서 바로 UN하지 않고, UN의 부분은 모두 뒤로 밀려났다.
이 스케줄은 정상적으로 작동할까?
T13에서 LS(B)를 실행할 수 있을까? 이미 T12에서 배타락 LX(B)을 건 상태이므로, 공유락과 배타락은 양립될 수 없기에 T13는 대기하게 된다. T13이 유지되고 있는 상태에서 T12가 A라는 데이터에 배타락(LX(A))을 요청한다. 그러나 이미 A데이터는 T13에 공유락(LS(A))되어 있는 상태다. 그래서 T12도 대기 상태가 된다. T12, T13이 서로의 요청이 끝날때까지 기다리고 있는 상황인 것이다. 이를 교착상태라 하며 롤백 없이는 영원히 유지된다.
교착상태(deadlock)
- 두 트랜잭션 중 하나를 롤백
- 한 트랜잭션이 롤백되면 그 트랜잭션이 획득했던 모든 락은 반납
락을 일찍 반납하면 일관성이 훼손되고, 락을 늦게 반납하면 교착상태에 부딫힌다. 이를 해소하기 위해 이른 반납과 지연 반납 사이의 규약.
하나의 트랜잭션이 연산을 수행하면서 필요한 데이터에 관한 락을 획득하기만 하다가, 하나의 데이터에 대한 반납이 이루어지는 순간부터 축소단계로 이루어져 반납만 가능하게 된다.
굉장히 유명한 락킹규약. 2PL(Two-Phase Locking Protocol)이라고도 부른다.
각 트랜잭션 Ti 실행의 순서를 판단하기 위해 타임스탬프 TS(Ti)를 부여
타임스탬프: 시간 보장. 언제 어떤 이벤트가 밸생했음을 명시할 때 타임스탬프를 사용한다. 어떤 트랜잭션이 DBMS에 진입하여 시행요청할 때, 그 시간을 타임스태프라 부름
데이터 항목에 대한 타임스탬프 할당
트랜잭션 뿐 아니라 사용되는 데이터에게도 타임스탬프라 부여된다. Ti가 어떤 데이터 Q에 대해 쓰기작업을 수행하면 W-TS(Q)는 Ti의의 Ts로 같이 결정된다. 이 중에서 가장 마지막에 수행했던 타임스탬프를 WTS라고 한다.
타임스탬프 순서 규약: 먼저 들어온 트랜잭션(타임스탬프가 작은)은 먼저 수행되도록 함으로써 직렬성 확보
Ti가 시작되고 나중에 Tj가 시행됨. Ti가 값을 작성해 Q값이 변경될 예정인데 그 전에 Tj가 Q를 읽어버림. 잘못된 값을 읽은 상태.
이런 경우를 고려하여, TS(Ti)와 W-TS(Q)를 비교해 롤백하거나 연산을 수행한다.
읽으려는 시간보다 최종 작성(쓰기) 시간이 최신이면 롤백 수행
내가 읽은 값을 누가 수정하려고 하면 롤백
TS(Ti)=내가 읽으려고 함. W-TS(Q) =누가 Q를 덮어씀.
TS(Ti) < W-TS(Q): 내가 이미 읽었는데 누가 그거 수정함 => 문제됨
TS(Ti) >= W-TS(Q): 누가 수정먼저하고 나서 내가 읽음 =>문제 안됨
Ti의 값이 최종적으로 작성되어 Tj가 입력한 값은 무시되고 Ti의 값만 남게됨.
내가 쓰려는 시간보다 최종 읽기,쓰기 시간이 더 최신이면 롤백 수행
내가 쓰려는 값을 이미 누가 읽거나 썼으면 롤백
1. TS(T14) < TS(T15)
< 만들어진 스케쥴 >
이 스케쥴은 정상적으로 작동 될까?
T15의 Read(B)
T15의 Write(B)
T14의 Read(A)
T15의 Read(A)
T15의 Write(A)
=> 일관성 손상없이 정상 작동 가능한 스케줄!
토마스라는 연구자가 타임스탬프 규약에 개선점을 제시함.
나보다 나중에 실행된 트랜잭션에서의 쓰기값은, 최종결과가 나보다 나중에 실행된 트랜잭션의 값으로 남는게 옳기때문에, 굳이 값을 쓰지 않더라도 문제 없다. 즉, 굳이 롤백하지 않고 쓰기값만 무시하고 Ti는 처리하는 것이 맞다.
롤백 자체가 DBMS에게는 큰 부담을 주는 연산이므로, 이 롤백의 연산을 줄여줌으로써 DBMS의 성능 개선이 가능하다.
뮈치겠다. 너무 헷갈린다.
해결방법: 두 트랜잭션 중 하나를 반드시 롤백
교착상태 발생이 비교적 높은 시스템의 경우
교착상태 발생이 비교적 높지 않은 시스템의 경우
교착상태가 드물게 생김. 미리 교차상태 장지 규약으로 DBMS 성능을 떨구는것보다, 일단 맘대로 처리해, 발생하면 롤백할게!하는 것이 더 낫다. 교착상태를 트랜잭션이 DBMS에 보고하지 않고, DBMS가 알고리즘으로 교착상태 발생 여부를 탐지함. 회복은 일정 트랜잭션을 롤백시키는 것을 말함
wait-die기법(비선점유 기반): TS(Ti) < TS(Tj)일 때 Ti가 기다리고 그렇지 않으면 Ti를 롤백.
(Ti가 먼저 시행됐으면 Ti가 Tj가 락을 반납할 때까지 기다린다. Ti가 나중에 시행됐으면 롤백한다.)
선점유: 특정 값에 의해 우선순위를 매겨두고 우선순위로 먼저 작업이 처리되도록 함. 비선점유: 우선순위로 작업순위를 매기지 않음.
wait | die |
---|---|
![]() | ![]() |
T18 = 대기 | T20 = 롤백 |
wound-wait 기법(선점유 기반): TS(Tj) < TS(Ti)일 때 Ti가 기다리고 그렇지 않으면 Tj를 롤백.
선점유기법으로 타임스탬프를 특정 우선순위로 둔다. 타임스탬프가 더 낮은것은 먼저 실행되었기 때문에, 먼저 락을 요구할 권리가 있다고 본다. 나중에 실행된 트랜잭션은 먼저 실행된 트랜잭션의 락을 요구하는 경우는 기다린다
wound | wait |
---|---|
![]() | ![]() |
T18은 바로 Q에 대한 락을 획득하고, T19는 락을 해제하고 롤백한다. | T20은 T19가 락을 해제할때까지 대기한다. |
(우선순위가 T18 > T19이므로) | (우선순위가 T19 > T20이므로) |
어떤 트랜잭션이 어떤 데이터항목을 가지고 있는지 정보를 쭉 가지고 있다가, 교착상태 판별 알고리즘을 주기적으로 돌려서, 발생 발견시 해결
대기 그래프(wait-for graph)를 이용하여 확인
대기 그래프에 사이클이 있다면 교착 상태가 발생
교착상태 X | 교착상태 O |
---|---|
![]() | ![]() |
교착상태 아님. T15가 끝나기만 대기하면 됨. | 서로 물고 물리는 순환 관계(사이클)가 생김. |
회복은 어떻게 할까? 롤백을 해야만 회복이 가능하다. 롤백을 수행하는 대상자를 희생자라고 이야기한다. 롤백 대상은 어떻게 선정할까? 아무나 선정하면 될까? 그렇지 않다. 롤백을 가장 빨리 할 수 있도록, 트랜잭션 시행 사태가 가장 짧은 트랜잭션이 좋지 않을까?
희생자 선정: 롤백 비용이 가장 적은 트랜잭션을 선택
희생자 롤백: 어느 시점까지 롤백 할 것인지 결정
무한정 기다림 해결