세이브포인트

세이브포인트

출처: 문서

본문

1. 구문

savepoint-stmt:

SAVEPOINT savepoint-name

release-stmt:

RELEASE SAVEPOINT savepoint-name

rollback-stmt:

ROLLBACK TRANSACTION TO SAVEPOINT savepoint-name

2. 세이브포인트

SAVEPOINT는 BEGIN 및 COMMIT처럼 트랜잭션을 만드는 방법이에요. 다만 SAVEPOINT와 RELEASE 명령은 이름을 가지며 중첩될 수 있어요.

SAVEPOINT 명령은 이름이 있는 새 트랜잭션을 시작해요. 트랜잭션 이름은 고유할 필요가 없어요. SAVEPOINT는 BEGIN...COMMIT 안이나 밖에서 시작할 수 있어요. SAVEPOINT가 가장 바깥쪽 savepoint이고 BEGIN...COMMIT 내부에 있지 않다면, 동작은 BEGIN DEFERRED TRANSACTION과 동일해요.

ROLLBACK TO 명령은 데이터베이스 상태를 해당 SAVEPOINT 직후의 상태로 되돌려요. 일반 ROLLBACK 명령(TO 키워드 없음)과 달리 ROLLBACK TO 명령은 트랜잭션을 취소하지 않아요. ROLLBACK TO 명령은 트랜잭션을 취소하는 대신 트랜잭션을 시작 지점부터 다시 시작해요. 다만 그 사이의 모든 SAVEPOINT는 취소돼요.

RELEASE 명령은 SAVEPOINT에 대한 COMMIT과 비슷해요. RELEASE 명령은 이름이 일치하는 가장 최근 savepoint를 포함해 그 이전의 모든 savepoint를 트랜잭션 스택에서 제거해요. 내부 트랜잭션의 RELEASE는 데이터베이스 파일에 어떤 변경도 기록하지 않아요. 단지 트랜잭션 스택에서 savepoint를 제거하여 해당 savepoint로 ROLLBACK TO 할 수 없게 만들 뿐이에요. RELEASE 명령이 가장 바깥쪽 savepoint를 해제하여 트랜잭션 스택이 비게 되면, RELEASE는 COMMIT과 동일해요. COMMIT 명령은 트랜잭션이 원래 BEGIN 명령이 아니라 SAVEPOINT 명령으로 시작되었더라도 모든 savepoint를 해제하고 트랜잭션을 커밋하는 데 사용할 수 있어요.

RELEASE 명령의 savepoint-name이 현재 트랜잭션 스택에 있는 어떤 savepoint와도 일치하지 않으면, 해제되는 savepoint는 없고 데이터베이스는 그대로이며, RELEASE 명령은 오류를 반환해요.

내부 트랜잭션은 RELEASE 명령으로 커밋할 수 있지만, 이후 외부 트랜잭션의 ROLLBACK으로 그 작업이 취소될 수 있음에 유의하세요. 정전이나 프로그램 크래시, OS 크래시가 발생하면 가장 바깥쪽 트랜잭션이 롤백되어, 그 외부 트랜잭션 안에서 발생한 모든 변경이 취소돼요. 여기에는 RELEASE 명령으로 "커밋"된 것으로 간주된 변경도 포함돼요. 실제로 디스크에 커밋되는 시점은 가장 바깥쪽 트랜잭션이 커밋될 때까지예요.

RELEASE 명령에 대해 생각할 수 있는 몇 가지 관점이 있어요.

  • 어떤 사람들은 RELEASE를 SAVEPOINT에 대한 COMMIT과 동등한 것으로 봐요. 내부 트랜잭션이 커밋한 변경이 나중에 외부 트랜잭션의 롤백으로 취소될 수 있다는 점만 기억한다면, 이는 받아들일 수 있는 관점이에요.

  • 또 다른 관점은 RELEASE가 이름 있는 트랜잭션을 부모 트랜잭션에 병합하여, 해당 트랜잭션과 부모 트랜잭션이 동일한 트랜잭션이 된다는 것이에요. RELEASE 이후에는 이름 있는 트랜잭션과 부모 트랜잭션이 어떤 운명을 맞든 함께 커밋되거나 롤백돼요.

  • savepoint를 트랜잭션 타임라인의 "표시"로 생각할 수도 있어요. 이 관점에서 SAVEPOINT 명령은 새 표시를 만들고, ROLLBACK TO 명령은 타임라인을 이름이 지정된 표시 직후 지점으로 되감으며, RELEASE 명령은 데이터베이스에 실제로 어떤 변경도 하지 않고 타임라인에서 표시를 지워요.

3. 트랜잭션 중첩 규칙

마지막으로 시작된 트랜잭션이 가장 먼저 커밋되거나 롤백돼요.

BEGIN 명령은 트랜잭션 스택이 비어 있을 때만, 즉 대기 중인 트랜잭션이 없을 때만 작동해요. BEGIN 명령을 호출했을 때 트랜잭션 스택이 비어 있지 않으면 명령은 오류와 함께 실패해요.

COMMIT 명령은 모든 미해결 트랜잭션을 커밋하고 트랜잭션 스택을 비워요.

RELEASE 명령은 트랜잭션 스택에 가장 최근에 추가된 것부터 시작하여, 이름이 일치하는 savepoint를 해제할 때까지 시간을 거슬러 savepoint를 해제해요. 그 이전의 savepoint는 이름이 일치하더라도 변경되지 않아요. RELEASE 명령으로 트랜잭션 스택이 비어지면(즉, 가장 바깥쪽 트랜잭션을 스택에서 해제하면) 트랜잭션이 커밋돼요.

TO 절이 없는 ROLLBACK 명령은 모든 트랜잭션을 롤백하고 트랜잭션 스택을 비워요.

TO 절이 있는 ROLLBACK 명령은 시간을 거슬러 올라가며 이름이 일치하는 가장 최근 SAVEPOINT까지 트랜잭션을 롤백해요. 이름이 일치하는 SAVEPOINT는 트랜잭션 스택에 남아 있지만, 해당 SAVEPOINT가 생성된 후 발생한 모든 데이터베이스 변경은 롤백돼요. ROLLBACK TO 명령의 savepoint-name이 스택에 있는 어떤 SAVEPOINT와도 일치하지 않으면, ROLLBACK 명령은 오류와 함께 실패하고 데이터베이스 상태는 그대로 유지돼요.

더 알아보기 (Learn more)