본문 바로가기
Database/SQL

TCL

by curious week 2026. 2. 11.

 

TCL

1) TRANSACTION

트랜잭션 = “하나의 작업 단위”로

TCL이란 한마디로, 변경 내용을 언제 확정(COMMIT)하고 언제 되돌릴지(ROLLBACK) 통제하는 언어

DB 입장에서 중요한 건 두 가지다.

  • 중간 상태가 외부에 보이면 안 됨 (Atomicity)
  • 성공하면 영구히 반영돼야 함 (Durability)

 

2) BEGIN / START TRANSACTION

트랜잭션 시작을 나타낸다.

BEGIN;
-- 또는
START TRANSACTION;

둘은 사실상 동일.

트랜잭션 없이 UPDATE 하면:

UPDATE users SET age = 0 WHERE age IS NULL;

→ 바로 반영됨
→ 사고 나면 되돌릴 방법 없음

트랜잭션 안에서 하면:

BEGIN;

UPDATE users SET age = 0 WHERE age IS NULL;

-- 확인
SELECT * FROM users WHERE age = 0;

COMMIT;

문제 있으면 롤백 가능

ROLLBACK;

 

 

PostgreSQL에서는

  • 기본적으로 autocommit 모드
  • 각 쿼리가 자동으로 BEGIN→COMMIT 처리됨

그래서 명시적으로 BEGIN을 써야 “여러 쿼리를 하나로 묶을 수 있음”.

3) COMMIT

트랜잭션을 영구 반영

COMMIT;
  • WAL에 기록
  • 다른 세션에서도 보임
  • 되돌릴 수 없음

사고 포인트

이걸 잘못 이해하면:

BEGIN;

DELETE FROM orders;  -- 전체 삭제

COMMIT;

→ 복구 불가 (백업 없으면 끝)

그래서 운영에서는:

  • COMMIT 전 반드시 SELECT로 영향 범위 확인
  • 대량 작업은 단계별 COMMIT

4) ROLLBACK

트랜잭션 전체 취소

ROLLBACK;

BEGIN 이후 변경된 모든 것 전부 원상복구

  • INSERT
  • UPDATE
  • DELETE
  • ALTER

사용 패턴

배포/마이그레이션:

BEGIN;

ALTER TABLE users ADD COLUMN phone TEXT;

UPDATE users SET phone = 'unknown' WHERE phone IS NULL;

-- 문제 발생
ROLLBACK;

DB 상태 그대로 유지됨.

5) SAVEPOINT (부분 롤백)

트랜잭션 내부에 “체크포인트” 만들기

BEGIN;

UPDATE users SET age = 0 WHERE age IS NULL;

SAVEPOINT step1;

UPDATE users SET age = -1; -- 실수

ROLLBACK TO step1;

COMMIT;

결과:

  • 첫 UPDATE는 유지
  • 두 번째 UPDATE만 취소

대량 작업 중:

BEGIN;

INSERT ... 100만건

SAVEPOINT batch1;

INSERT ... 다음 100만건

중간에 에러:

ROLLBACK TO batch1;

→ 앞 작업은 유지
→ 이후 작업만 재시도 가능

이게 없으면:

  • 전체 ROLLBACK
  • 처음부터 다시 해야 함

6) SET TRANSACTION (격리수준/읽기전용)

트랜잭션의 “동작 방식”을 정하는 옵션.

BEGIN;

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION READ ONLY;

SELECT * FROM orders;

COMMIT;

주요 옵션

(1) Isolation Level (격리 수준)

트랜잭션 간 “서로 데이터를 얼마나 볼 수 있냐”를 결정.

READ COMMITTED (Postgres 기본)

  • COMMIT된 데이터만 읽음
  • 가장 일반적인 운영 모드
  • 문제는 같은 SELECT 명령을 두 번 했을 때→ 값 다를 수 있음

REPEATABLE READ

  • 트랜잭션 시작 시점 snapshot 고정 같은 SELECT 반복해도 동일 결과
  • 중간에 다른 세션이 바꿔도 안 보임

SERIALIZABLE

  • 가장 엄격
  • 트랜잭션 충돌 시 에러 발생 및 트랜잭션을 롤백
SELECT *
FROM accounts
WHERE id = 1
FOR UPDATE;
  • 행을 락으로 잡아버림(쓰기 잠금) → 다른 트랜잭션 UPDATE 못 함
  • 금융 시스템 대부분은 이걸 사용.

(2) READ ONLY

SET TRANSACTION READ ONLY;
  • UPDATE/DELETE 금지
  • 분석용 트랜잭션 (리포트/배치에서 매우 중요)

7) SET LOCAL

트랜잭션 “내에서만” 적용되는 설정.

BEGIN;

SET LOCAL work_mem = '256MB';

SELECT ... 대량 정렬 쿼리

COMMIT;

트랜잭션 끝나면:

  • 자동으로 원래 값으로 복귀

운영에서 많이 씀 특정 쿼리만 메모리 크게, 특정 트랜잭션만 timeout 다르게 설정 할 수 있음.

8) TCL이 실제 성능과 연결되는 지점

(1) 트랜잭션 길이 = 성능 영향

트랜잭션 오래 열어두면:

  • MVCC snapshot 유지
  • vacuum 지연
  • 테이블 bloat 증가
  • 다른 세션 락 대기

긴 트랜잭션 = 성능 문제를 야기 할 수 있음.

(2) COMMIT 타이밍 = WAL 부담

COMMIT 할 때마다:

  • WAL flush 발생

대량 INSERT에서:

  • 1건마다 COMMIT → 느림
  • 1000건마다 COMMIT → 훨씬 빠름

(3) 격리수준 = 락 전략 변화

SERIALIZABLE:

  • 충돌 감지
  • rollback 발생 가능
  • 높은 안정성 vs 성능 저하

READ COMMITTED:

  • 성능 좋음
  • 대신 phantom read(이미 바뀐 결과를 읽음) 가능성

9) 기억하면 좋은 패턴 3개

패턴 1 — 안전 UPDATE

BEGIN;

SELECT COUNT(*) FROM users WHERE age IS NULL;

UPDATE users SET age = 0 WHERE age IS NULL;

COMMIT;

 

패턴 2 — 배치 처리

BEGIN;

INSERT ...

SAVEPOINT batch1;

INSERT ...

SAVEPOINT batch2;

COMMIT;

패턴 3 — 분석 트랜잭션

BEGIN;
SET TRANSACTION READ ONLY;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

SELECT ...

COMMIT;

 

'Database > SQL' 카테고리의 다른 글

Lock과 성능 개선  (0) 2026.02.11
INSERT, UPDATE, DELETE  (0) 2026.02.10
ALTER, DROP, TRUNCATE  (0) 2026.02.10
CREATE  (0) 2026.02.10
String, Date  (0) 2026.02.09