데이터베이스는 다수의 사용자가 동시에 사용하더라도 항상 모순이 없는 정확한 데이터를 유지해야 한다. 그리고 데이터베이스에 장애가 발생하더라도 빠른 시간 내에 원래의 상태로 복구할 수 있어야 한다. 트랜잭션을 관리함으로써 데이터베이스의 회복과 병행 제어가 가능해져, 결과적으로 데이터베이스가 일관된 상태를 유지할 수 있게 된다.
트랜잭션은 작업 하나를 수행하는데 필요한 데이터베이스의 연산들을 모아놓은 것으로, 데이터베이스에서 논리적인 작업의 단위가 된다.
트랜잭션을 사용하게 된다면, 계좌 이체 실행 중 에러가 발생해도 rollback()을 통해 원상태로 복구할 수 있다는 장점이 있다.
트랜잭션이 성공적으로 처리되어 데이터베이스의 무결성과 일관성이 보장되려면 다음 네 가지 특성을 꼭 만족해야 한다. 트랜잭션의 네 가지 특성을 각 특성에 해당하는 영어 단어의 첫 자를 따서 ACID 특성이라고 한다.
원자성 atomicity
트랜잭션의 원자성은 트랜잭션을 구성하는 연산들이 모두 정상적으로 실행되거나 하나도 실행되지 않아야 한다는 all-or-nothing 방식을 의미한다.
만약 트랜잭션을 수행하다가 장애가 발생하여 작업을 완료하지 못했다면, 지금까지 실행한 연산 처리를 모두 최소하고 데이터베이스를 트랜잭션 작업 전의 상태로 되돌려 트랜잭션의 원자성을 보장해야 한다.
일관성 consistency
트랜잭션의 일관성은 트랜잭션이 성공적으로 수행된 후에도 데이터베이스가 일관된 상태를 유지해야 함을 의미한다. 즉 트랜잭션이 수행되기 전에 데이터베이스가 일관된 상태였다면 트랜잭션의 수행이 완료된 후 결과를 반영한 데이터베이스도 또 다른 일관된 상태가 되어야 한다는 의미다.
격리성 isolation
트랜잭션의 격리성은 고립성이라고도 하는데, 현재 수행 중인 트랜잭션이 완료될 때까지 트랜잭션이 생성한 중간 연상 결과에 다른 트랜잭션들이 접근할 수 없음을 의미한다. 일반적으로 데이터베이스 시스템에서는 여러 트랜잭션이 동시에 수행되지만, 각 트랜잭션이 독립적으로 수행될 수 있도록 다른 트랜잭션의 중간 연산 결과에 서로 접근하지 못하게 한다.
지속성
트랜잭션의 지속성은 영속성이라고도 하는데, 트랜잭션이 성공적으로 완료된 후 데이터베이스에 반영한 수행 결과는 어떠한 경우에도 손실되지 않고 영구저깅어야 함을 의미한다. 즉, 시스템에 장애가 발생하더라도 트랜잭션 작업 결과는 없어지지 않고 데이터베이스에 그대로 남아 있어야 한다는 의미다.
트랜잭션의 수행과 관련하여 주로 사용되는 연산에는 작업 완료를 의미하는 commit 연산과 작업 취소를 의미하는 rollback 연산이 있다.
commit은 트랜잭션의 수행이 성공적으로 완료되었음을 선언하는 연산이다. commit 연산이 실행된 후에야 트랜잭션의 수행 결과가 데이터베이스에 반영되어 데이터베이스가 일관된 상태를 지속적으로 유지하게 된다.
rollback은 트랜잭션의 수행이 실패했음을 선언하는 연산이다. rollback 연산이 실행되면 트랜잭션이 지금까지 실행한 연산의 결과가 취소되고 트랜잭션이 수행되기 전의 상태로 돌아간다.
활동 상태
트랜잭션이 수행되기 시작하여 현재 수행 중인 상태를 활동 상태라고 한다. 활동 상태인 트랜잭션은 상황에 따라 부분 완료 상태나 실패 상태가 된다.
부분 완료 상태
트랜잭션의 마지막 연산이 실행된 직후의 상태를 부분 완료 상태라 하는데, 이는 트랜잭션의 모든 연산을 처리한 상태다. 부분 완료 상태인 트랜잭션은 모든 연산의 처리가 끝났지만 트랜잭션이 수행된 최종 결과를 데이터베이스에 아직 반영하지 않은 상태다. 따라서 아직은 트랜잭션의 수행이 성공적으로 완료됐다고 볼 수 없다. 부분 완료 상태의 트랜잭션은상황에 따라 완료 상태나 실패 상태가 될 수 있다.
완료 상태
트랜잭션이 성공적으로 완료되어 commit 연산을 실행한 상태를 완료 상태라고 한다. 트랜잭션이 완료 상태가 되면 트랜잭션이 수행한 최종 결과를 데이터베이스에 반영하고, 데이터베이스가 새로운 일관된 상태가 되면서 트랜잭션이 종료된다.
실패 상태
하드웨어나 소프트웨어의 문제, 트랜잭션 내부의 오류 등 여러 이유로 인해 장애가 발생하여 트랜잭션의 수행이 중단된 상태를 실패 상태라고 한다. 트랜잭션을 더는 정상적으로 수행할 수 없을 때 실패 상태가 된다.
철회 상태
트랜잭션을 수행하는데 실패하여 rollback 연산을 실행한 상태를 철회 상태라고 한다. 트랜잭션이 철회 상태가 되면 지금까지 실행한 트랜잭션의 연산을 모두 취소하고 트랜잭션이 수행되기 전의 데이터베이스 상태로 되돌리면서 트랜잭션이 종료된다.
트랜잭션의 특성을 보장하고 데이터베이스를 모순이 없는 일관된 상태로 유지하기 위해 데이터베이스 관리 시스템은 회복 기능을 제공한다.
시스템이제대로 동작하지 않는 상태를 장애라고 한다. 장애가 발생하는 원인은 사용자의 실수, 하드웨어 고장, 소프트웨어의 논리적인 오류 등 다양한 이유가 있다.
일반적으로 데이터베이스는 비휘발성 저장 장치인 디스크에 상주한다. 하지만 트랜잭션이 데이터베이스의 데이터를 처리하려면, 데이터를 디스크에서 메인 메로리로 가져와 이를 처리한 후 그 결과를 다시 디스크로 보내는 작업이 필요하다.
디스크와 메인 메모리 간의 데이터 이동은 대개 블록 단위로 수행된다. 디스크에 있는 블록을 디스크 블록이라 하고, 메인 메모리에 있는 블록을 버퍼 블록이라 한다.
디스크와 메인 메모리 간의 데이터 이동은 다음 두 연산으로 수행된다.
사용자의 요구에 따라 응용 프로그램에서 트랜잭션의 수행을 지시하면 메인 메모리 버퍼 블록에 있는 데이터를 프로그램의 변수로 가져오고, 데이터 처리 결과를 저장한 변수 값을 메인 메모리 버퍼 블록으로 옮기는 작업이 필요하다.
회복은 데이터베이스에 장애가 발생했을 때 장애가 발생하기 전의 모순이 없고 일관된 상태로 복구시키는 것으로, 데이터베이스 관리 시스템에 있는 회복 관리자가 담당한다.
회복을 위한 연산
데이터베이스 회복의 핵심 원리는 데이터 중복이다. 데이터를 별도의 장소에 미리 복사해두고, 장애로 문제가 발생했을 떄 복사본을 이용해 원래의 상태로 복원하는 것이다. 덤프 또는 로그 방법을 사용해 데이터를 복사해 두었다가 회복시킬 때 복사본을 사용한다.
데이터베이스 전체를 복사하는 덤프 방법은 한달에 한 번과 같이 미리 정해진 주기에 따라 수행한다. 그리고 디스크와 같은 비휘발성 장치에 저장한다.
장애가 발생했을 떄, 덤프나 로그 방법으로 중복 저장한 데이터를 이용해 데이터베이스를 복구하는 기본적인 방법은 redo나 undo 연산을 실행하는 것이다.
redo 연산과 undo 연산을 실행할 땐 로그가 중요하게 사용된다.
로그 회복 기법
로그를 이용한 회복 기법은 데이터를 변경한 연산 결과를 데이터베이스에 반영하는 시점에 따라 즉시 갱신 회복 기법과 지연 갱신 회복 기법으로 나뉜다.
즉시 갱신 회복 기법
즉시 갱신 회복 기법은 트랜잭션 수행 중에 데이터를 변경한 연산의 결과를 데이터베이스에 즉시 반영한다. 그리고 장애 발생에 대비하기 위해 데이터 변경에 대한 내용을 로그 파일에도 기록한다.
지연 갱신 회복 기법
지연 갱신 회복 기법은 트랜잭션이 수행되는 동안에는 데이터 변경 연산의 결과를 데이터베이스에 즉시 반영하지 않고 로그 파일에만 기록해두었다가, 트랜잭션이 부분 완ㄴ료된 후에 로그에 기록된 내용을 이용해 데이터베이스에 한 번에 반영한다.
데이터베이스 관리 시스템은 여러 사용자가 데이터베이스를 동시에 공유할 수 있도록 여러개의 트랜잭션이 동시에 수행되는 병행 수행을 지원한다. 병행 수행은 실제로 여러 트랜잭션이 차례로 번갈아 수행되는 인터리빙 방식으로 진행된다.
여러 개의 트랜잭션이 병행 수행되면서 같은 데이터에 접근하여 연산을 실행하더라도 문제가 발생하지 않고 정확한 수행 결과를 얻을 수 있도록 트랜잭션의 수행을 제어하는 것을 병행 제어 또는 동시성 제어라고 한다.
병행 수행을 특별한 제어 없이 진행하면 여러 문제가 발생할 수 있다.
갱신 분실
갱신 분실은 하나의 트랜잭션이 수행한 데이터 변경 연산의 결과를 다른 트랜잭션이 덮어써 변경 연산이 무효화되는 것이다.
갱신 분실을 방지하기 위해서는 이처럼 순차적으로 수행한 것과 같은 결과값을 얻을 수 있어야 한다.
모순성
모순성은 하나의 트랜잭션이 여러 개의 데이터 변경 연산을 실행할 때 일관성 없는 상태의 데이터베이스에서 데이터를 가져와 연산을 실행함으로써, 모순된 결과가 발생하는 것이다.
예를 들어 어떤 연산은 현재의 트랜잭션이 실행되기 전 상태의 데이터베이스에서 데이터를 사져와 실행하고 ,또 다른 연산은 다른 트랜잭션이 변경한 데이터베이스에서 데이터를 가져와 실행하면 모순성의 문제가 발생할 수 있다.
연쇄 복귀
연쇄 복귀는 트랜잭션이 완료되기 전에 장애가 발생하여 rollback 연산을 수행하면, 이 트랜잭션이 장애 발생 전에 변경한 데이터를 가져가 변경 연산을 실행한 또 다른 트랜잭션에도 rollback 연산을 연쇄적으로 실행해야 한다는 것이다.
그런데, 장애가 발생한 트랜잭션이 rollback 연산을 실행하기 전에 변경한 데이터를 가져가 사용하는 다른 트랜잭션이 수행을 완료해버리면, rollback 연산을 실행할 수 없어 큰 문제가 발생하게 된다.
직렬 스케줄
직렬 스케줄은 인터리빙 방식을 이용하지 않고 트랜잭션별로 연산들을 순차적으로 실행시키는 것이다. 트랜잭션이 직렬 스케줄에 따라 수행되면, 모든 트랜잭션이 완료될 때까지 다른 트랜잭션의 방해를 받지 않고 독립적으로 수행된다.
직렬 스케줄은 동시에 수행되지 않기 때문에 일반적으로 잘 사용되지 않는다.
비직렬 스케줄
비직렬 스케줄은 인터리빙 방식을 이용하여 트랜잭션을 병행해서 수행시키는 것이다. 비직렬 스케줄은 트랜잭션이 돌아가면서 연산들을 실행하기 때문에, 하나의 트랜잭션이 완료되기 전에 다른 트랜잭션의 연산이 실행될 수 있다.
비직렬 스케줄에 따라 여러 트랜잭션을 병행 수행하면 갱신 분실, 모순성, 연쇄 복귀 등의 문제가 발생할 수 있어 최종 수행 결과의 정확성을 보장할 수 없다.
직렬 가능 스케줄
직렬 가능 스케줄은 직렬 스케줄에 따라 수행한 것과 같이 정확한 결과를 생성하는 비직렬 스케줄이다.
직렬 가능 스케줄을 이용해 트랜잭션을 병행 수행해야 하지만 직렬 가능 스케줄인지 여부를 판단하는 일은 쉽지 않다. 다수의 트랜잭션을 대상으로 비직렬 스케줄을 찾아내는 것이 어려 울 뿐만 아니라, 하나씩 수행해보면서 직렬 스케줄과 같은 결과가 나오는지 비교하는 것도 간 단한 작업이 아니기 때문이다. 그래서 대부분의 데이터베이스 관리 시스템에서는 직렬 가능 스케줄인지를 검사하기보다는 직렬 가능성을 보장하는 병행 제어 기법을 사용한다.
병행 제어 기법은 여러 트랜잭션을 병행 수행하면서도 정확한 결과를 얻을 수 있는 직렬 가능 성을 보장받기 위해 사용한다. 병행 제어 기법의 기본 원리는 모든 트랜잭션이 따르면 직렬 가능성이 보장되는 나름의 규약을 정의하고, 트랜잭션들이 이 규약을 따르도록 하는 것이다. 그러므로 트랜잭션 스케줄이 직렬 가능 스케줄인지를 미리 검사할 필요가 없다. 스케줄 내의 모든 트랜잭션이 병행 제어 기법에서 정의한 규약을 따르면 해당 스케줄은 직렬 가능성을 보 장할 수 있다.
로킹 기법의 개념
로킹locking 기법은 병행 수행되는 트랜잭션들이 동일한 데이터에 동시에 접근하지 못하도록 lock과 니nlock이라는 2개의 연산을 이용해 제어한다. 로킹 기법의 기본 원리는 한 트랜잭션 이 먼저 접근한 데이터에 대한 연산을 모두 마칠 때까지, 해당 데이터에 다른 트랜잭션이 접 근하지 못하도록 상호 배제mutual exclusion하여 직렬 가능성을 보장하는 것이다.
2단계 로킹 규약
기본 로킹 규약의 문제를 해결하고 트랜잭션의 직렬 가능성을 보장하기 위해 lock과 unlock 연산의 수행 시점에 대한 새로운 규약을 추가한 것이 2단계 로킹 규약이다. 트랜잭션 스케줄의 모든 트랜잭션이 2단계 로킹 규약을 준수하면 해당 스케줄은 직렬 가능성이 보장된다. 2단계 로킹 규약을 따르려면 모든 트랜잭션이 lock과 unlock 연산 을 다음과 같이 2단계로 나누어 실행해야 한다.