TCL(Transaction Control Language)은 데이터베이스에서 트랜잭션(논리적인 작업 단위)를 제어하는데 사용되는 SQL 명령어들이다. 이를 통해 데이터의 일관성과 무결성을 보장할 수 있다.
트랜잭션은 하나의 작업 단위로 묶인 여러 SQL 문장들을 말한다. 예를 들어 은행 계좌 이체는 다음 두 가지 작업이 동시에 이루어져야 한다.
이 두 작업 중 하나라도 실패하면 전체 작업이 취소되어야 한다. 이처럼 모든 작업이 성공하거나, 아니면 모두 실패해야 하는 것이 트랜잭션이다.
TCL은 다음 ACID 원칙을 만족시키기 위해서 사용된다.
| 명령어 | 설명 |
|---|---|
| COMMIT | 트랜잭션의 모든 변경 사항을 영구 저장 |
| ROLLBACK | 트랜잭션 내에서 발생한 변경 사항을 모두 취소 |
| SAVEPOINT | 트랜잭션 내에서 롤백 가능한 중간 지점 설정 |
| RELEASE SAVEPOINT | 설정한 저장 지점 제거 |
| SET TRANSACTION | 트랜잭션의 속성(격리 수준 등)을 설정 |
변경사항을 확정하고 DB에 영구 반영한다.
BEGIN;
UPDATE accounts
SET balance = balance - 100
WHERE id = 1;
UPDATE accounts
SET balance = balance + 100
WHERE id = 2;
COMMIT;
두 UPDATE가 모두 성공했을 때 COMMIT으로 반영한다.
트랜잭션 중 문제가 생기면 되돌린다.
BEGIN;
UPDATE accounts
SET balance = balance - 100
WHERE id = 1;
ROLLBACK;
위 업데이트는 취소되고, DB는 원래 상태로 복구된다.
트랜잭션 중간에 되롤릴 지점을 지정할 수 있다.
BEGIN;
UPDATE accounts
SET balance = balance - 100
WHERE id = 1;
SAVEPOINT sp1; -- 세이브포인드
UPDATE accounts
SET balance = balance + 100
WHERE id = 2;
ROLLBACK TO sp1;
COMMIT; -- 커밋을 실행하면 세이브포인트는 자동으로 삭제된다.
두 번째 UPDATE만 되돌리고, 첫 번째 UPDATE는 유지하고 COMMIT할 수 있다.
ROLLBACK되면 세이브포인트는 소멸한다.더 이상 필요 없는 저장 지점을 제거한다.
RELEASE SAVEPOINT sp1;
COMMIT 또는 ROLLBACK 되었을 때.BEGIN;
SAVEPOINT sp1;
-- 다른 쿼리들
-- sp1 더 이상 필요 없으면 제거
RELEASE SAVEPOINT sp1;
COMMIT; -- 어차피 이 시점에 모든 세이브포인트는 사라짐
리소스 관리와 성능 최적화 때문이다. 세이브포인트가 많아지면 아래와 같은 문제가 생긴다.
ROLLBACK TO시에 어떤 지점으로 돌아가야 할지 DB가 더 많은 상태 정보를 추적해야 하므로 복구나 트랜잭션 실행 성능에 영향을 줄 수따라서 RELEASE SAVEPOINT를 사용하는 이유는 다음과 같다.
| 목적 | 설명 |
|---|---|
| 불필요한 세이브포인트 제거 | 더 이상 사용하지 않을 세이브포인트를 명시적으로 제거해 메모리 절약 |
| 성능 최적화 | 트랜잭션 중간에 세이브포인트 수를 줄여 복구 시 오버헤드 감소 |
| 리소스 관리 | 장시간 실행되는 트랜잭션에서 불필요한 상태 유지 방지 |
트랜잭션의 격리 수준을 설정한다.
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
-- 다른 쿼리들
COMMIT;
격리 수준은 동시에 여러 트랜잭션이 실행될 때, 서로 간섭하지 않도록 하는 정도를 말한다. ANSI SQL에서는 다음과 같은 4가지 격리 수준이 정의되어있다.
| 격리 수준 | 허용되는 현상 | 설명 |
|---|---|---|
| READ UNCOMMITED | 더티 리드 가능 | 다른 트랜잭션의 미롼료 데이터를 읽을 수 있다 |
| READ COMMITED | 더티 리드 방지 | 커밋된 데이터만 읽는다 |
| REPEATABLE READ | 터티 리드, 논리적 오류 방지 | 읽은 행은 트랜잭션 종료시까지 고정한다 |
| SERIALIZABLE | X | 트랜잭션을 순차적으로 실행한 것처럼 보이게 한다 |
다음은 각 상황 별로 예시를 든 SQL이다.
-- 데이터 정합성이 최우선일 때
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
-- 예금 인출 + 입금
COMMIT;
-- 성능이 중요하고, 최신 데이터만 보고 싶을 때
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 트랜잭션이 읽기 전용임을 명시하고 싶을 때
SET TRANSACTION READ ONLY;
BEGIN;
SELECT *
FROM board;
COMMIT;
REPEATABLE READ이고, ProstgreSQL은 기본적으로 READ COMMITED이다.