설치·접속: PostgreSQL 설치와 접속
부제: 여러 스텝짜리 정산 트랜잭션에서 한 스텝만 잘못됐는데, 전체를 롤백하지 않고 그 지점부터 다시 진행하고 싶을 때
트랜잭션은 all-or-nothing이라고 배운다. 하지만 SAVEPOINT를 찍어두면 그 지점까지의 작업은 남기고 이후만 되돌릴 수 있다. Alice에서 100을 차감하고 저장점을 찍은 뒤, Bob에게 잘못 입금했다가 그 입금만 취소하고, 다시 Wally에게 입금해 커밋하는 공식 예제로 확인한다.
CREATE TABLE acct (name text PRIMARY KEY, balance numeric);
INSERT INTO acct VALUES ('Alice', 1000), ('Bob', 1000), ('Wally', 1000);
BEGIN;
UPDATE acct SET balance = balance - 100.00 WHERE name = 'Alice';
SAVEPOINT my_savepoint;
UPDATE acct SET balance = balance + 100.00 WHERE name = 'Bob';
-- "Bob이 아니라 Wally였다" → Bob 입금만 취소, Alice 차감은 유지
ROLLBACK TO my_savepoint;
UPDATE acct SET balance = balance + 100.00 WHERE name = 'Wally';
COMMIT;
SELECT * FROM acct ORDER BY name;
name | balance
-------+---------
Alice | 900.00
Bob | 1000
Wally | 1100.00Alice는 100 차감된 900이 그대로 유지됐고, Bob 입금은 ROLLBACK TO my_savepoint로 취소되어 1000, 그 뒤 Wally 입금이 반영된 1100으로 커밋됐다. 저장점 이전(Alice 차감)은 살고, 저장점 이후~롤백 사이의 작업(Bob 입금)만 사라진 것이다.
ROLLBACK TO는 트랜잭션을 끝내지 않는다. 저장점 이후 변경만 되감고 트랜잭션은 계속 열려 있어, 곧바로 다른 경로로 이어서 진행할 수 있다. 배치 처리 중 한 스텝이 실패했을 때 전체를 날리고 처음부터 다시 하는 대신, 실패 지점의 저장점으로 돌아가 대체 경로를 태우는 부분 복구에 쓴다. 함정 하나 — 되돌린 저장점 이름은 ROLLBACK TO 후에도 살아 있어 다시 롤백 대상이 되고, 그 저장점 이후에 새로 찍었던 저장점들은 함께 무효가 된다.
이렇게도 쓴다
같은 저장점으로 여러 번 되돌릴 수 있다 — 저장점은 ROLLBACK TO 후에도 남는다.
SAVEPOINT sp;
UPDATE acct SET balance = balance - 10 WHERE name = 'Alice';
ROLLBACK TO sp; -- 1차 취소
UPDATE acct SET balance = balance - 20 WHERE name = 'Alice';
ROLLBACK TO sp; -- 같은 sp로 2차 취소
RELEASE SAVEPOINT로 저장점을 확정 병합해 더 이상 되돌릴 수 없게 한다.
SAVEPOINT sp;
UPDATE acct SET balance = balance + 50 WHERE name = 'Bob';
RELEASE SAVEPOINT sp; -- 이 변경은 이제 되돌릴 수 없다(커밋 시 반영)
문장 에러로 트랜잭션이 abort 상태에 빠졌을 때, 저장점으로 돌아가 트랜잭션을 살린다.
SAVEPOINT sp;
INSERT INTO acct VALUES ('Alice', 0); -- PK 중복 에러 → 트랜잭션 abort
ROLLBACK TO sp; -- abort 해제, 트랜잭션 계속 진행 가능
저장점을 중첩해 다단계 정산을 스텝별로 되감는다.
SAVEPOINT step1; -- ... 작업 ...
SAVEPOINT step2; -- ... 작업 ...
ROLLBACK TO step2; -- step2만 취소, step1은 유지
PL/pgSQL에서는 BEGIN ... EXCEPTION 블록이 암묵 저장점 역할을 한다. (조합: 에러 핸들링)
BEGIN
UPDATE acct SET balance = balance - 100 WHERE name = 'Alice';
EXCEPTION WHEN others THEN
RAISE NOTICE 'step failed, rolled back to block start: %', SQLERRM;
END;
psql에서 문장별 자동 저장점을 켜 실패한 문장만 되돌린다. (조합: ON_ERROR_ROLLBACK)
\set ON_ERROR_ROLLBACK on
-- 이후 각 문장 실패는 직전 상태로만 자동 롤백되고 트랜잭션은 생존'명령어 > DB' 카테고리의 다른 글
| [PostgreSQL] WHEN 조건 트리거 — 값이 실제로 바뀔 때만 발화시켜 no-op UPDATE를 흘려보낸다 (0) | 2026.08.02 |
|---|---|
| [PostgreSQL] \watch 같은 쿼리를 주기적으로 반복 실행한다 (0) | 2026.08.02 |
| [PostgreSQL] DELETE 했는데 용량이 안 줄고 오히려 느려질 때 — VACUUM과 bloat (0) | 2026.08.02 |
| [PostgreSQL] 미사용·중복 인덱스 색출 — pg_stat_user_indexes로 안 쓰는 57MB 걷어내기 (0) | 2026.08.02 |
| [PostgreSQL] pg_trgm GIN — `LIKE '%foo%'` 선행 와일드카드를 인덱스로 (0) | 2026.08.02 |