명령어/DB

[PostgreSQL] SAVEPOINT / ROLLBACK TO — 트랜잭션을 통째로 날리지 않고 한 스텝만 되돌린다

jykim23 2026. 8. 4. 22:52
반응형

설치·접속: 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.00

Alice는 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
-- 이후 각 문장 실패는 직전 상태로만 자동 롤백되고 트랜잭션은 생존
반응형