CodeGym /행동 /SQL SELF /SAVEPOINT을(를) 이용한 부분 롤백 관리하기

SAVEPOINT을(를) 이용한 부분 롤백 관리하기

SQL SELF
레벨 39 , 레슨 2
사용 가능

책을 쓴다고 상상해봐. 근데 항상 계획대로 되는 건 아니잖아? 가끔은 한 챕터를 다 썼는데, 다시 읽어보니까 5번째 단락이 완전 별로야. 그럴 때 어떻게 해? 챕터 전체를 휴지통에 버리진 않지? 대신에 문제 있는 부분만 고치잖아.

SAVEPOINT도 PostgreSQL에서 딱 그런 느낌이야. 이걸로 할 수 있는 건:

  1. 트랜잭션 안에 저장 포인트를 만들 수 있어 — 책에 북마크 꽂는 거랑 비슷하지.
  2. 그 포인트로 돌아가서, 트랜잭션 전체가 아니라 일부 작업만 취소할 수 있어.
  3. 나머지 데이터는 그대로 두고, 처음부터 다시 시작하지 않아도 돼.

SAVEPOINT 기본 문법

SAVEPOINT 관련 명령어는 진짜 간단해. 기본 세트는 이거야:

저장 포인트 만들기 (SAVEPOINT):

SAVEPOINT savepoint_name;

이건 "여기까지 저장해둘게, 나중에 필요하면 돌아올 수도 있으니까" 이런 느낌이야.

저장 포인트로 롤백하기 (ROLLBACK TO SAVEPOINT):
ROLLBACK TO SAVEPOINT savepoint_name;

뭔가 잘못됐을 때, 지정한 SAVEPOINT로 돌아가서 그 이후의 변경만 취소할 수 있어.

저장 포인트 삭제하기 (RELEASE SAVEPOINT):
RELEASE SAVEPOINT savepoint_name;

이건 북마크를 없애는 거야. 이걸 하고 나면 그 포인트로는 더 이상 돌아갈 수 없어.

간단 예제: 온라인 쇼핑몰에서 구매하기

온라인 쇼핑몰을 운영한다고 해보자. 고객이 장바구니에 여러 상품을 담고, 우리는 주문 처리랑 재고 테이블 업데이트를 트랜잭션으로 처리하고 싶어. 근데 중간에 한 단계가 실패하면, 전체가 아니라 일부만 롤백하고 싶지.

BEGIN;

-- 1단계: "SQL 책" 상품 예약하기
UPDATE inventory SET stock = stock - 1 WHERE product_id = 101;

-- 저장 포인트 만들기
SAVEPOINT book_reserved;

-- 2단계: "PostgreSQL 머그컵" 상품 예약하기
UPDATE inventory SET stock = stock - 1 WHERE product_id = 102;

-- 어이쿠, 머그컵 재고가 없네!
ROLLBACK TO SAVEPOINT book_reserved;

-- 책만 변경된 내용 커밋하기
COMMIT;

이 예제에서 무슨 일이 일어나는지 볼까?

  1. BEGIN으로 트랜잭션을 시작해.
  2. 책을 예약한 다음 book_reserved라는 저장 포인트를 만들었어. 이게 첫 번째 "체크포인트"야.
  3. 머그컵도 예약하려고 했는데, 에러가 났어 (예를 들어 재고가 없어서).
  4. book_reserved 저장 포인트로 롤백해서, 머그컵 관련 변경만 취소했어.
  5. 마지막으로 COMMIT으로 책에 대한 변경만 확정했어.

좀 더 복잡한 예제: 여러 단계 데이터 처리

이번엔 주문 관리 시스템에서 여러 테이블을 업데이트해야 한다고 해보자: orders (주문), inventory (재고), billing (청구). 중간에 뭔가 꼬이면, 다른 테이블에서 한 작업까지 다 날리고 싶진 않잖아. 이럴 때 SAVEPOINT이(가) 진짜 유용해.

BEGIN;

-- 1단계: 새 주문 생성
INSERT INTO orders (order_id, customer_id, status) VALUES (1, 123, '대기중');
SAVEPOINT after_order_created;

-- 2단계: 재고 업데이트
UPDATE inventory SET stock = stock - 2 WHERE product_id = 101;
SAVEPOINT after_stock_updated;

-- 3단계: 결제 처리
INSERT INTO billing (order_id, amount, status) VALUES (1, 100, '결제완료');

-- 어이쿠, 신용카드가 거절됐어!
ROLLBACK TO SAVEPOINT after_stock_updated;

-- 재고 업데이트까지만 남기고, 주문 상태를 "실패"로 바꿔
UPDATE orders SET status = '실패' WHERE order_id = 1;

COMMIT;

SAVEPOINT으로 트랜잭션을 논리적 단계로 나누고, 필요한 포인트로 돌아가서 일부 변경만 남기는 걸 볼 수 있어.

SAVEPOINT 쓸 때 유용한 팁

  • 저장 포인트 이름을 의미 있게 지어. 위 예제처럼 after_order_createdstep1보다 훨씬 알아보기 쉽지.
  • 중첩 저장 포인트도 잘 작동해: 다른 포인트로 롤백한 후에도 SAVEPOINT을(를) 또 만들 수 있어.
  • 필요 없는 저장 포인트는 RELEASE SAVEPOINT로 지워서 리소스를 아껴. 특히 큰 트랜잭션에서는 성능에 도움 돼.

실전에서 쓰는 예시

은행 거래 처리: 여러 계좌로 금액을 이체할 때, 한 번이라도 실패하면 특정 단계까지만 롤백할 수 있어.

파일에서 데이터 가져오기: 큰 CSV 파일을 임포트할 때, 각 줄을 검사해서 에러 난 데이터만 롤백하고, 성공한 건 남길 수 있어.

대량 레코드 업데이트: 수천 줄을 업데이트하는 복잡한 SQL 스크립트에서, 중간에 에러가 나면 이전 단계로 롤백할 수 있어.

자주 하는 실수와 함정

가끔 SAVEPOINT을(를) 잘못 쓰면 예상치 못한 결과가 나올 수 있어. 예를 들면:

  • 저장 포인트로 롤백하거나 삭제하는 걸 까먹으면, 트랜잭션 끝날 때까지 리소스가 잠길 수 있어.
  • SAVEPOINT은(는) 저장 포인트 만들기 전의 작업은 취소 못 해. 예를 들어 COMMIT으로 확정된 데이터는 롤백 불가야.

이제 트랜잭션에서 필요한 곳에 저장 포인트를 만들어서 안전하게 실험할 수 있어. 앞으로 더 많은 SQL 실습이 기다리고 있으니까, 다음 모험도 준비해!

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION