트랜잭션이란 더 이상 쪼갤 수 없는 프로그램 실행의 최소단위로 승인(commit)혹은 철회(abrot, rollback) 두 가지의 결과만을 가진다. 즉, 트랜잭션의 모든 작업이 성공하면 데이터베이스에 반영(commit)하고, 만약 트랜잭션 중 하나의 작업이라도 실패하면 처음 상태로 돌아가야 한다(rollback). 트랜잭션의 이러한 특징 때문에 시스템 오류나 하드웨어의 고장으로 발생하는 결함(Failures)과 여러 트랜잭션들이 동시에 실행되는 상황(Concurrent execution)에서 발생하는 문제들을 처리하는 방법이 필요하다.
일반적으로 하나의 어플리케이션은 여러개의 트랜잭션으로 이루어져있고, 각 트랜잭션은 여러 sql구문의 집합으로 나타낼 수 있다. 그리고 어플리케이션이 데이터에 접근하기 위해서는 JDBC와 같은 인터페이스를 통해 트랜잭션의 sql을 DBMS에 전달하여 결과 데이터를 얻을 수 있다.
read(A)
A := A - 50
write(A)
read(B)
B := B - 50
write(B)
commit
위의 예시를 보면 하나의 트랜잭션 안에서 read(A), write(A), read(B), write(B)가 순서대로 수행된다. 이들 각각은 sql구문으로 치환되어 DBMS에 전달되면 DBMS는 각 sql쿼리에 맞는 작업을 수행한 뒤 결과를 돌려준다. 이때 중요한 점은 read와 write등의 작업은 DBMS의 버퍼에서 이루어진다는 것이다. 즉, 트랜잭션에서 read(A) 를 요청하면 DBMS는 먼저 버퍼에 A가 있는지 확인한 후, 값이 있으면 그 값을 반환하고 없으면 디스크에서 I/O를 통해 A값을 버퍼로 올린 뒤 어플리케이션에게 전달한다. 그 다음 A := A - 50 이 어플리케이션 내부에서 실행된 다음 결과값을 write(A)를 통해 DB에 반영한다. 이때에도 A값은 버퍼에만 반영되고 디스크에는 반영되지 않는다.
DBMS에서 버퍼의 내용을 디스크에 쓰는 시점은 버퍼가 가득 차 페이지를 교체해야하거나 복구 프로세스가 수행될 때이기 때문에 데이터의 변경은 디스크에 즉시 반영되지 않는다. 따라서 최신값은 항상 버퍼에 존재하게 되고 만약 찾는 데이터가 버퍼에 없으면 디스크에서 I/O를 통해 값을 올린다. 이렇게 데이터를 디스크에 바로 쓰지 않는 이유는 I/O횟수를 최소화하기 위함인데, 만약 디스크에 반영되지 않은 데이터가 버퍼에 남아있는데 시스템의 고장이 발생하여 버퍼의 내용이 날아가게 된다면 고장복구 프로세스등을 통해 버퍼의 값을 복원해야 한다.
ACID란 트랜잭션이 안전하게 수행될 수 있도록 DBMS가 보장해야 하는 성질로 각각 Atomicity, Consistency, Isolation, Durability를 의미한다.
한 트랜잭션은 특정 시점에 위의 그림과 같은 5가지 상태 중 하나를 가진다.