트랜젝션은 데이터베이스에서 CRUD가 일어나는 하나의 작업단위이다.
즉 DB의 DML(Data Modification Language)인 SELECT, INSERT, UPDATE, DELETE 작업이 단위 별로 발생하면 그것을 트랜잭션이라 한다.
주의할 것은, DML이 한 번 일어났다고 트랜잭션이 한 번 발생한 것은 아닐 수도 있다는 점.
예를 들어 회원가입 기능을 생각해보자.
가입 버튼을 누르면 DB에서는 다음과 같은 DML들이 수행될 것이다.
이처럼 CRUD가 하나의 작업을 위해 여러 번 수행될 수도 있으므로
이 경우엔 하나의 트랜잭션으로 본다.
트랜잭션을 다루기 위한 언어를 TCL(Transaction Control Language)라고 하며,
대표적으로 Commit, Rollback, Savepoint가 있다.
이 명령어들은 트랜잭션이 끝났음을 confirm하거나, 트랜잭션을 다시 되돌리는 데 필요하다.
DML 쿼리를 계속 날려도 Commit을 하지 않으면,
Rollback 한 번이면 다시 맨 처음으로 되돌아간다.
Insert, Update를 100번 했더라도 Commit하지 않은 상태에서 Rollback하면
100번 모두 무효가 된다는 의미다.
그 이유는 당연한 것이, 하나의 거래 단위 - 트랜잭션이 발생하기까지는 다양한 DML이 필요한데,
중간에 그 중 하나라도 이상이 생기면 거래 전체를 중단시켜야 하기 때문이다.
온라인 송금 트랜잭션을 생각하면 쉽다.
내 계좌에서 돈이 빠져나가긴 했는데(Update),
남의 계좌로 돈이 들어가는 과정(Update)에서 문제가 생긴다면?
내 계좌로 다시 돈이 들어오지 않고 중단되면 돈은 그냥 중간에서 증발해버릴 것이다.
TIP : SAVEPOINT
TCL의 Savpoint는 특정 시점에서 트랜잭션을 취소하기 위해 시점을 저장하는 명령어로,
Savepoint를 설정해두면 Rollback시 이 Savepoint까지만 상태가 되돌아간다.
위 은행거래를 다시 잘 생각해보면,
우리는 트랜잭션이 가지는 4가지 특징 - ACID(산성..이 아니다)를 도출해낼 수 있다.
원자성이라니 말이 어려운데…사실 별 것 아니다.
원자는 더 이상 분리할 수 없는 특징을 갖는 것 처럼(쿼크..는 무시하자),
하나의 트랜잭션은 쪼개질 수 없이 All-or-Nothing의 특징을 가진다.,
즉, 되려면 다 수행되거나, 아니면 Rollback 아예 원상태로 돌아가거나 한다는 의미.
위 은행거래의 예시가 트랜잭션의 원자성이라 할 수 있겠다.
트랜잭션이 일어나기 전 조건이나 상태는 트랜잭션 이후에도 계속 지켜져야 한다는 뜻.
가령 회원가입의 DML이 수행된다고 하자.
이 때 회원ID에는 무결성 제약조건으로 Not NULL 조건이 있을 것이다.
따라서 회원정보 수정 후에도, 그 결과는 여전히 Not NULL 이어야 한다.
만약 기존 조건을 만족하지 못한다면 해당 트랜잭션은 deny 되어야 한다.
(단, 결과 이전 과정에서 이러한 상태 변동은 일어날 수 있고, 결과만 만족하면 됨)
동기화 - 비동기화 와 같은 개념과 마찬가지로,
트랜잭션은 다른 트랜잭션의 간섭을 받아서도, 서로 참조해서도 안된다.
그런데..고립성을 강하게 보장한다면 DB자체의 성능문제가 발생하지 않을까?
그래서 고립성에도 등급이 있다고 한다(Isolation Level - 트랜잭션 격리수준)
이 등급별로 고립성을 지키는 기준이 다르므로(보통 Commit으로 기준을 정함),
DB 성능에도 영향을 미치게 된다.
즉, 고립성과 성능은 Trade-off 관계이다.
Durability - 지속성
우리의 데이터는 소중하므로,
DML을 완료 하고 Commit하면 그 기록이 영구히 지속되는 것을 의미한다.
그렇다면..commit하다가 갑자기 정전 등으로 데이터처리에 장애가 생기면 어떡하는가?
그래서 많은 DBMS들이 Logging(로깅)을 활용한다.
로깅은 말 그대로 ‘변화의 기록’이라 할 수 있다.
데이터의 변화 과정을 기록하여 영구 보존장치(현실에는 존재하지 않음)에 저장해놓으면 이상적일 것…이나, 현실은 녹록치 않으므로,
DBMS는 비휘발성 디스크 등에 상태를 기록해놓는다(파일형태로 존재).
그리고 Rollback이 필요하거나 불완전한 트랜잭션이 발생했을 경우
로그 레코드를 참고하여 데이터를 원상태로 돌릴 수 있다.
다시 말하면, 트랜잭션은 로그에 모든 것이 저장된 후에만 Commit된 것이라 볼 수 있다.