본문 바로가기

CS 과목(CS科目)/데이터 베이스(データベース)

16. concurrency control - Part 2

unrecoverable schedule

위 그림에서 보듯, transaction1은 commit의 명령어를 만나면서 실행이 종료가 돼, H의 balance=250만원인 상태가 DB 서

버에 영구적으로 저장이 됐다. ( 참고로, 이 commit은 Transaction1에 대한 commit이므로, Transaction2에 해당하는 빨간색

으로 표시된 2개의 명령문에 대해서는 commit이 되지 않는다.) 

그런데, Transaction2에서 어떤 예기치 못한 에러가 발생을 하여, ABORT(중단)가 되면, Transaction2에 대해 roll back

실행이 돼(autocommit에 의해 에러 발생 시, 자동으로 roll back이 실행이 된다), Transaction2의 Operation들의 실행이 모

두 무효화되고, Transaction2가 시작되기 이전의 상태로 복구가 된다. 

 transaction2가 시작되기 이전의 H의 balance는 200만원이였으므로 H의 balance는 200만원으로 복구가 되어서 아무

문제가 없는 것처럼 보인다. 

Transaction2의 유효하지 않은 Operation에 의해 roll back이 일어나서 H의 balance는 transaction 시작 이전의 상태로 돌

아 왔지만,  그 밑에 이어지는 Transaction1의 Operation들은 그 위의 2개의 유효하지 않은 Operation의 결과값을 읽어 들

(read)  값을 쓰고(write), 최종적으로 commit에 의해 DB 서버에 영구적으로 유효하지 않은 결과값이 저장이 됐다.

그래서 해당 Transaction 1에 대해서도 roll back을 실행을 하여 데이터를 복구를 하고 싶지만, 이미 Transactino1에 대해서

는 commit이 실행이 됐으므로 Transaction의 durability 속성에 의해서 데이터의 복구가 불가능하다. 

( Transaction2의 Operation의 결과값인 230만원을 읽어 들여서 Transaction1의 Operation들이 20만원을 H에게 이체를 해

버렸다. 고로, transactino1에 대해 roll back을 해주지 않으면, K는 balance가 80만원이 되고, H는 200만원이 된다. K는 100

만원에서 80만원으로 잔고가 줄었으므로, 20만원을 손해를 보는 불상사가 생긴다.)

 

unrecoverable schedule은 roll back을 해도 이전 상태로 회복 불가능할 수 있기 때문에 이런 schedule은 DBMS가 허용을

하면 안된다.   

고로, 핵심은 DBMS는 recoverable schedule만을 허락해야 한다. 

그럼 어떤 schedule이 recoverable한 schedule일까???? 

-> A 트랜잭션이 만약 B 트랜잭션에 의존하고 있다면, commit에 의해서 트랜잭션이 종료되던, roll back에 의해서 트랜잭

이 종료되던, 항상 의존하고 있는 B 트랜잭션을 마지막에 종료시켜야 된다. 

( 풀어서 다시 정의를 하자면, schedule 내에서 어떤 transation도 [commit되지 않은 transaction들이 write한 데이터]를

읽지 않는 schedule)

트랜잭션1이 트랜잭션2의 write() Operation에 의존을 하고 있으므로, transaction1의 commit이 마지막에 실행됨. 

트랜잭션 1의 roll back이 마지막에 실행이 됨. 

cascading roll back (연속적 roll back)

트랜잭션 2번이 roll back을 하면, 트랜잭션2에 의존하고 있는 트랜잭션1도 같이 roll back을 무조건 해줘야 한다. 

이러한 roll back을 cascading roll back이라고 한다. 

여러 트랜잭션을 연속적으로(cascading) roll back을 시키려면, 많은 처리 비용이 든다. 

그럼 어떻게 해결을 할 수가 있을까??( cascadeless schedule로 해결이 가능 )

cascadeless schedule(avoid cascading schedule이라고 부르기도 한다)

데이터를 write한 transaction이 commit을 하던, roll back을 하던  그 트랜잭션이 종료가 된 뒤에만 다른 트랜잭션들이

데이터를 읽게 하는 schedule. ( 아래에서 자세히 살펴보자 )

트랜잭션1의 read()는 더이상 트랜잭션2의 write()에 의존하지 않는다. 

만약, 트랜잭션2에서 에러가 발생돼 roll back이 발생되면, 트랜잭션2에 대해서만 roll back을 실행을 하고 아래와 같이

독립적인 관계인 트랜잭션 1에서는 트랜잭션 2가 마치 없었던 것처럼 데이터를 read()하여 작업을 진행해 나가면 된다.

이때, roll back은 연속적으로 일어나지 않고, 트랜잭션2에 대해서만 roll back을 하면 된다. 

 

그럼 cascadless schedule은 완벽한 schedule인가???

이 schedule도 어떤 경우에는 issue가 생길 수도 있다.( 아래에서 예제를 가지고 살펴보자 )

strict schedule 

 schedule 내에서 어떤 transation도 [commit되지 않은 transaction들이 write한 데이터]를 읽지도, 쓰지도 않는 schedule.

최종적으로는 피자값이 3만원에서 2만원으로 변경이 되어 있어야 한다.

위 schedule은 cascadless schedule이다. 

맨 처음 트랜잭션1에서는 직원이 실수로 피자 가격을 1만원으로 설정을 했다.

트랜잭션2에서는 사장님이 피자 가격을 2만원으로 설정을 하였고, 여기에서 commit이 실행이 된다.

다시 트랜잭션 1로 돌아와서 나머지 operation을 실행을 하였는데, 이때 abort에 의해 roll back이 실행이 됐다고 하자.

그럼 transaction1이 시작되기 이전의 피자 가격으로 복구가 되므로, 피자 가격은 최종적으로 3만원이 된다.

즉, 트랜잭션2가 정상적으로 실행을 마치고 저장한 피자 가격 2만원이 3만원으로 덮어 씌여져 버렸다. 

이걸 해결하기 위해서 나온 것이 strict schedule이라는 개념이다. (아래에서 자세히 설명)

 

이제는 commit/rollback에 의해서 종료되지 않은 트랜잭션에서 write된 데이터에 대해서는 write하지 못하는 상황이다.

2가지의 case에 대해 살펴보자

1. 트랜잭션1은 commit, 트랜잭션2에서 roll back

-> 트랜잭션 2에서 roll back이 되면, 피자값이 1만원으로 된다. 

2. 트랜잭션1에서 roll back이 일어나는 경우

->  트랜잭션2에 의해 피자 가격이 2만원이 된다.

---> strict schedule에 의해서, 어떠한 트랜잭션에서 에러가 발생하여 roll back을 해도, 이전처럼 다른 트랜잭션의 정상적인

결과값이 덮어 씌여 지는 일은 없다.