concurrency control 2 : recoverability

이혁진·2022년 12월 5일
0

0. reference

https://velog.io/@dd9s2/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-Recovery-Concurrency-Control
https://youtu.be/89TZbhmo8zk

1. recovery

트랜잭션을 수행하던 도중 장애가 발생하여 DB가 손상되었을 때, 손상 이전의 상태로 복구하는 작업을 말한다.

장애에는 트랜잭션 장애(모호한 데이터, 과다 자원 요구), 시스템 장애(데드락, SW 손상), 미디어 장애(디스크 손상)가 있다.

트랜잭션 실행이 실패하면 해당 트랜잭션이 만든 변화를 rollback하고, 이전 상태로 복구한다. 이때 메모리 덤프와 로그를 사용한다.

메모리 덤프 : DB 전체를 주기적으로 복사해두는 것
로그 : DB 갱신 전후의 내용을 기록하는 파일

그 기법에는 4가지 정도가 있다

  1. deferred update : commit까지 DB 갱신을 유보한다
  2. immediate update : 갱신 즉시 DB 반영, log에 변화를 기록
  3. shadow paging : 디비를 page단위로 복사해놓음, 장애 시 대체
  4. check point : 로그에 체크포인트 보관, 거기부터 recovery

2. schedule recoverability

2.1. unrecoverable schedule

rollback한 트랜잭션이 write했던 데이터를 read하고, commit한 경우 그 스케줄을 unrecoverable schedule이라 한다.

이전처럼 은행의 계좌 이체를 하는 상황을 가정해보자. 동운이(D)는 재이(J)에게 500원을 이체해야 하고, 재이는 1000원을 빼간다고 해보자. 그것을 처리하는 트랜잭션은 다음과 같이 정의한다.

read는 r로, write는 w, commit은 c, abort은 a 그 뒤의 번호는 오퍼레이션의 트랜잭션을 구분하기 위한 숫자로 하겠다. 또한, 동운의 초기 잔고는 10000원이고 재이의 초기 잔고는 20000원이다.

// 동운이 재이에게 500원을 이체하는 트랜잭션 
t1 : (r1(D)=>x, w1(D=x-500), r1(J)=>y, w1(J=y+500))

// 재이가 1000원을 빼가는 트랜잭션
t2 : (r2(J)=>z, w2(J=z-1000))

<schedule.1>	
r1(D)=>10000
w1(D=9500)
				r2(J)=>20000
				w2(J=19000) !!
r1(J)=>19000 !!
w1(J=19500)
c1
				a2 : rollback(J=20000)
                

t1은 t2가 write한 데이터를 commit되지 않은 채로 read하여 작업을 commit했고, t2는 그 후에 rollback을 진행했다. 원래라면 롤백이 되었을 때, 그 변화가 r1(J)에 반영되어야 하나 이미 commit된 상태이기에 불가능해진 것이다. a2만 롤백하게 되면, J=20000 이고 J=19500인 데이터 불일치가 발생하게 된다.

위 정의를 보다 이해하기 쉽게 하기 위하여 의존자와 피의존자라는 개념을 도입한다.

피의존자란 어떤 데이터를 단순히 write한 트랜잭션(t2)이고, 그 동일한 데이터를 후에 read한 트랜잭션(t1)이 의존자이다.

그러면 위 정의는 다음과 같이 바뀐다.

unrecoverable schedule이란 의존자가 피의존자의 commit/rollback 이전에 commit을 진행했고, 피의존자가 후에 rollback된 것을 말한다.

피의존자의 모든 변화가 의존자에 반영되어야 하는 것은 당연한데, 피의존자의 변화가 확정(commit/rollback)이전에 의존자를 commit한다는 뜻이므로 그 뒤에 무슨 일이 일어나도 의존자에겐 반영이 되지 않는다. 이는 롤백을 포함한다. 다시말하면 이미 commit해서 롤백해도 이전 상태로 돌리는 회복이 불가능할 수 있다는 뜻이다.

아무튼 위 스케줄은 롤백을 하더라도 회복이 불가능할 수 있어, DBMS가 허용해선 안된다.

2.2. recoverable schedule

어떤 트랜잭션도 자신이 읽은 데이터를 write한 트랜잭션의 commit/rollback 전까지는 commit하지 않는 스케줄을 말한다.

recoverable schedule은 피의존자의 commit/rollback을 기다리기 때문에 unrecoverable schedule에서 빠른 commit에 의해 발생하는 데이터 불일치 문제를 막을 수 있다.

마찬가지로 정의를 단순화할 수 있다.

의존자는 피의존자의 commit/rollback 이후에만 commit을 진행한다.

중요한 것은 commit 순서이다. 피의존자가 반드시 먼저 commit해야만 한다. 그래야 의존자가 모든 피의존자의 변화를 확인하고 이를 반영할 수 있다.

<schedule.1>	
r1(D)=>10000
w1(D=9500)
				r2(J)=>20000
				w2(J=19000) !!
r1(J)=>19000 !!
w1(J=19500)
				a2 : rollback(J=20000)
                
a1 : rollback(D=10000, J=20000)
                

롤백을 성공적으로 반영할 수 있다. 이때 a2->a1처럼 의존관계에 의한 연쇄 롤백을 cascading rollback이라고 한다.

2.3. cascadeless schedule

어떤 트랜잭션도 commit되지 않은 트랜잭션이 write한 데이터를 read하지 않는 경우 cascadeless schedule이라고 한다.

다시 말하면, 의존자는 반드시 read한다면 피의존자가 commit한 후에 해야 한다는 것이다.

이는 recoverable schedule에 포함된다. 왜냐하면, t1:commit -> t2:read + ... -> t2:commit처럼, 의존자의 commit 혹은 rollback은 의존자의 operation 이후에 일어난다. cascadeless schedule에서 의존자 operation은 반드시 피의존자의 commit 이후에 발생하므로 cascadeless schedule은 recoverable schedule이라 할 수 있겠다.

// t1:commit -> t2:read + ... -> t2:commit
// t1:commit -> t2:commit (recoverable)

recoverable schedule로써 피의존자의 rollback 시에 그것에 의존하는 트랜잭션들을 rollback할 수 있게 되었다. 다만, 이러한 의존 관계가 복잡하게 얽혀있는 경우 롤백 비용이 상당히 소요되게 된다. 그래서 연쇄 롤백 없이, 단순히 피의존자의 롤백으로 recovery 과정을 끝낼 수 있는 cascading schedule이 나오게 되었다.

<schedule.1>	
r1(D)=>10000
w1(D=9500)

				r2(J)=>20000
				w2(J=19000) !!
                c2 or a2
                
r1(J)=>19000 or 20000 !!
w1(J=19500 or 20500)
c1(not related whether c2 or a2)

이전과는 달리, c1은 굳이 롤백을 하지 않더라도 데이터 불일치 없이 잘 recovery가 수행됨을 확인할 수 있다.

2.4. strict schedule

어떤 트랜잭션도 commit되지 않은 트랜잭션이 write한 데이터는 쓰지도 읽지도 않는 경우를 말한다.

cascadeless schedule에서 의존자의 범위를 피의존자에 write하는 것까지로 확장한 것과 같다.

이것이 필요한 이유는 다음 사례 때문이다.

<pizza schedule> 피자 가격 : 3만원
w1(pizza = 1만원)
					w2(pizza = 2만원)
                    c2
                    
a1 : rollback(pizza = 1만원)

cascadeless에서 정의하는 의존 관계 자체가 없으므로 cascadeless schedule이나, t1의 롤백 시 t2의 갱신 작업이 없어지게 된다. 이러한 이상 역시 recovery에서 막아야 한다고 생각하여 만들어진 것이 strict schedule이다.

조건을 만족하도록 스케줄을 수정하면

<pizza schedule> 피자 가격 : 3만원
w1(pizza = 1만원)
a1 : rollback(pizza = 1만원)

					w2(pizza = 2만원)
					c2

롤백 후에나 write를 하기에, w2 갱신이 사라지지 않게 된다.

정리

unrecoverable schedule
-> 롤백 시 회복 불가능(불일치 등)할 수 있다.
-> DBMS에서 허용하지 않아야 한다.
recoverable schedule
-> recover이 가능하고 dbms에서 허용한다.
cascadeless schedule
-> recoverable schedule 에서 조건을 더해 연쇄 롤백 방지
strict schedule
-> strict schedule 에서 조건을 더 추가해 이상한 현상 방지

recoveribility란, 올바른 commit 순서로 정상적 롤백이 가능한 스케줄을 말한다.

serializability란 순차 처리로 이상 현상이 없는 스케줄을 말한다.

concerrency control은 위의 롤백 가능, 병행(conflict serial)처리가 가능한 스케줄을 제공한다.

profile
한양대학교 정보시스템학과 22학번 이혁진 입니다

0개의 댓글