DBMS가 내가 명령한 처리를 제대로 시행못하고, 엉뚱한 결과를 출력한다면, 그 기능과 확장성을 떠나서 사용하기 힘든 DBMS일 것이다. 사용자의 요구를 "정확하게" 수행하기 위해서 DBMS는 어떤 기능을 가지고 있을까??
- 동일 데이터에 다수 사용자의 접근 허용 시 일관성이 훼손
고객 A가 500원을 출금하는 것과, 고객 B가 해당 계좌에 1000원을 입금하는 것이 동시에 이뤄진다면, 하나의 계좌에 2개의 다른 금액 상태가 발생한다. 하나의 데이터에 여러 작업이 동시에 수행될때 데이터의 일관성에 훼손이 발생한다.
DBMS는 다수의 사용자가 동시에 여러 형태의 데이터를 사용하기위해 모아놓은 데이터의 집합. DBMS는 어떻게 데이터의 일관성 훼손을 예방하면서 동일 데이터 요청을 처리할까?
다수의 연산으로 구성된 트랜잭션이 사용자에게 단일작업처럼 다뤄지도록 ACID 특징을 준수
(DBMS는 항상 ACID 특징을 준수해야 한다!)
ACID 특성
트랜잭션의 두 연산
계좌 A에서 B로 1,000원을 이체하는 트랜잭션
하나의 트랜잭션에 포함된 모든 연산은 완전히 수행되거나 전혀 수행되지 않음.
작업이 쭉 시행되다가 DBMS나 H/W에 오류로 A값에 1000원을 뺀 상태에서 기능이 정지되었으면, 이 상태에서 멈춰있을까? 아니다. 원자성에 의해 작업 처리 이전으로 되돌려보내는 과정을 가친다.
특정 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지
제일 처음 A와 B의 계좌에 각각 10000원씩 총 20000이 있었다. 트랜잭션을 시행하면서 A에서 1000원이 빠져서 일관성이 훼손된다. 그러나 쭉 작업이 처리되어 B에 1000원을 추가하여 A는 9000원, B는 11000원이 되어 다시 전체 계좌는 20000원이 된다. 트랜잭션 시행동안은 일관성이 훼손되었으나, 트랜잭션이 끝난 이후에는 최종 금액의 일관성을 원복한다.
특정 트랜잭션이 데이터베이스를 갱신하는 동안 다른 트랜잭션에 의해 방해받지 않음
처리되고 있는데, 갑자기 또다른 트랜잭션이 끼어들어서 A의 값을 출력하려고 한다. 아직 A의 값을 저장하지 않았으므로 또 다른 사용자가 A의 계좌를 읽으면 10000원으로 출력된다. 그러나 현재 A의 계좌는 천원을 제거한 9000원인 상태이다. 이런 불상사를 예방하기 위해, 하나의 트랜잭션이 처리되는 동안은, 다른 트랜잭션이 작업을 중단할 수 없다.
완료된 트랜잭션의 결과는 어떠한 시스템의 장애에도 데이터베이스에 반영이 되어야 함
트랜잭션이 끝나고 나면 A는 9000원, B는 11000원으로 종료된다. 정상적으로 작업이 끝나고 나면, 해당값이 영구적으로 지속되어야 한다. 만약 트랜잭션이 모두 끝난 이후, 하드디스크의 물리적 오류로 해당 데이터가 손상되더라도, DBMS는 지속성을 만족시키기위해 또 다른 곳에서 데이터를 불러와 이 최종값을 다시 원복시키는 과정을 수행한다.
실제 데이터가 어디에 있느냐에 따라 5가지 상태변화를 갖고 있다. 이 5가지 상태변화를 정확하게 파악하고 있어야 데이터가 어디까지 반영되고 반영되지 않았는지, 처리의 재수행 필요 여부를 확인할 수 있으므로 5단계를 정확하게 이해하고 있어야 한다.
정보를 동시에 다루려 드니까 문제가 되는거잖아. 그냥 데이터를 동시에 안다루면 다 끝날 문재인데, DBMS는 왜 계속 데이터 동시 사용을 고려하려고 하는걸까?
=> 처음부터 동시에 쓰는게 개발 목적. 대기시간 감소 (= 사용자 만족도신뢰도 향상)
서로 다른 데이터면 동시에 처리되어도 괜찮은거 아닌가?
어떻게 동시에 처리하면서, 동시에 처리하지 않은것과 같은 효과를 보여줄 수 있을까?
동시에 처리하려고 여러 요청이 한번에 들어오면, DBMS가 요청을 뒤죽박죽 늘어놓는 것이 아니라, 요청이 들어온 순서대로 쭉 늘어놓고 스케줄을 만든다. 그리고 이 스케줄을 보면서, 동시에 처리가 가능한지 판단해본다.
**스케줄(schedule)
- 다수의 트랜잭션에 포함된 연산의 실행 순서를 명시한 것.
직렬 스케줄
- 각 트랜잭션에 속한 모든 연산이 순차적으로 실행되는 스케줄
스케줄 3은 병렬 스케줄이지만 일관성이 훼손되지 않았다. 그에 해 케줄 4는 Read, Write를 뒤죽박죽 섞어가며 시행해 최종 금액이 A는 9000원, B는 22000원이 되어버린다. 일관성이 유지되지 않는다.
병렬 스케줄
- 하나의 트랜잭션이 완료되기 전에 다른 트랜잭션이 실행되는 스케줄
병렬 스케줄의 순서로 연산을 수행할 경우 일관성의 훼손이 발생 가능
이런 병렬 스케줄은 직렬로 변경해야 한다. 이를 위해 병렬 스케줄 중 일관성을 훼손시키는 스케줄을 파악할 수 있어야 한다!
직렬 가능 스케줄
- 복수개의 트랜잭션이 동시에 수행된 결과가 직렬 스케줄의 결과와 동일한 스케줄
트랜잭션의 연산자 자체가 read와 write밖에 없음. 2개의 교환에는 4개의 경우의 수 밖에 없음. 그 중, 충돌이 발생하지 않는 것은 read-read 교환밖에 없음. 연산자에 하나의 write라도 있으면 교환을 하면 안됨.
"동일한 데이터(A)"를 읽고 있을때 write의 변화가 있으면 충돌이 발생"한다.
Write(A) - Read(B) 서로 다른 데이터의 읽고 쓰기 이므로 교환을 해도 상관없다.
Write(A) - Write(B) 서로 다른 데이터를 다루고 있으므로 교환해도 상관없다.
연산의 순서를 교환해 만들어진 결과이나, 데이터의 최종 결과는 교환 이전과 동일할때, 이를 충돌 동등이라 한다.
충돌 동등은 유지한채 스케줄을 교환할 수 있다면, 이를 충돌 직렬성을 확보했다고 얘기한다.
스케줄 5번: 병렬 스케줄이지만 일관성이 훼손되지 않음. 충돌 직렬성을 가지고 있어 충돌 없이 직렬스케줄로 변환이 가능하므로 일관성에 훼손이 없었던 것.
스케줄 4번: 아무리 순서를 바꿔도 직렬 스케줄을 바꿀 수 없음. 충돌 직렬성을 확보하고 있지 못하기때문에 일관성이 훼손된 결과가 만들어 짐.
원자성을 보장하기 위해 트랜잭션 실패 시 실행된 모든 연산을 실행 이전 상태로 복원하는 개념
회복 불가능한 스케줄
Read(B)과정에서 실패가 발생해 rollback을 시행해야 하는 상황. 원복을 위해서 A에 쓴 값을 취소시켜야 하는데, T6에 Read(A) 후 commit한 상황이 문제가 된다. A의 값이 9000원임을 알려줬는데, 다시 원복시켜 만원으로 돌아간다면 T6에서 읽은 값은 잘못된 값. 그러나 이미 commit을 시켰으므로 값을 되돌리는 것은 지속성을 어긴다. 이 상황은, 회복이 불가능한 스케줄이 되었다.
모든 트랜잭션, 스케줄은 실패가 가능하므로 회복이 가능해야 한다. 이런식으로 회복이 불가능한 스케줄이 생기기 시작하면 데이터베이스의 일관성이 유지되지 못하므로 정확한 데이터를 가지고 있다 할 수 없다.
T7에서 abort라는 실패가 발생하면, 아직 T8, T9에서 commit이 없으므로 모두 rollback할 수 있다. 다만 연쇄적 롤백으로 인하여 하나의 트랜잭션 실패로 인해 다수의 트랜잭션이 모두 회복 연산을 시행해야한다는 부작용이 있다.
따라서 회복 가능하면서도, 비연쇄적인 스케줄을 만드는 것이 중요하다!
1.연쇄적 롤백으로 발생할 수 있는 대량의 회복 연산을 방지하기 위해 연쇄적이지 않은 스케줄로 구성된 스케줄
2. Ti가 기록한 데이터를 읽을 때 Ti의 커밋이 Tj의 읽기 연산보다 먼저 나타나는 스케줄
음.. 어려울게 없어 보이는데 막상 공부하면서 막막한 부분이 많았다. 근데 진짜로 어렵게 생각할 필요 없을거 같다. 복잡하게 생각할 것 없이, 마지막 그림을 최종 정답으로 생각하면 되지 않을까. commit하고 다음 트랜잭션이 read하는.. 방식으로....