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 |