트랜잭션

트랜잭션

이 페이지에서는 SQLite에서 트랜잭션을 시작하고 커밋하고 롤백하는 방법을 설명해요. 트랜잭션을 제어하는 BEGIN, COMMIT, ROLLBACK 명령어와 그 동작 방식을 다루어요.

출처: 문서

본문

begin-stmt:

BEGIN EXCLUSIVE TRANSACTION DEFERRED IMMEDIATE

commit-stmt:

COMMIT TRANSACTION END

rollback-stmt:

ROLLBACK TRANSACTION TO SAVEPOINT savepoint-name

2. 트랜잭션

읽기나 쓰기는 트랜잭션 안에서만 발생합니다. 데이터베이스에 접근하는 모든 명령(기본적으로 일부 PRAGMA 문을 제외한 모든 SQL 명령)은 이미 실행 중인 트랜잭션이 없으면 자동으로 트랜잭션을 시작합니다. 자동으로 시작된 트랜잭션은 마지막 SQL 문이 끝나면 커밋됩니다.

트랜잭션은 BEGIN 명령으로 수동으로 시작할 수 있습니다. 이러한 트랜잭션은 보통 다음 COMMIT 또는 ROLLBACK 명령까지 유지됩니다. 그러나 데이터베이스가 닫히거나 오류가 발생하고 ROLLBACK 충돌 해결 알고리즘이 지정된 경우에도 트랜잭션이 롤백됩니다. ROLLBACK 충돌 해결 알고리즘에 대한 자세한 내용은 ON CONFLICT 절 문서를 참조하세요.

END TRANSACTION은 COMMIT의 별칭입니다.

BEGIN...COMMIT으로 생성된 트랜잭션은 중첩되지 않습니다. 중첩 트랜잭션에는 SAVEPOINT 및 RELEASE 명령을 사용하세요. 위 구문 다이어그램에 표시된 ROLLBACK 명령의 "TO SAVEPOINT name" 절은 SAVEPOINT 트랜잭션에만 적용됩니다. 트랜잭션 내에서 BEGIN 명령을 호출하려 하면, 해당 트랜잭션이 SAVEPOINT로 시작되었든 이전 BEGIN으로 시작되었든 관계없이 오류와 함께 실패합니다. TO 절이 없는 COMMIT 명령과 ROLLBACK 명령은 SAVEPOINT 트랜잭션에서도 BEGIN으로 시작된 트랜잭션과 동일하게 작동합니다.

2.1. 읽기 트랜잭션과 쓰기 트랜잭션

SQLite는 별도의 데이터베이스 연결(별도의 스레드나 프로세스일 수 있음)에서 오는 여러 동시 읽기 트랜잭션을 지원하지만, 동시 쓰기 트랜잭션은 하나만 지원합니다.

읽기 트랜잭션은 읽기 전용으로 사용됩니다. 쓰기 트랜잭션은 읽기와 쓰기를 모두 허용합니다. 읽기 트랜잭션은 SELECT 문으로 시작되고, 쓰기 트랜잭션은 CREATE, DELETE, DROP, INSERT, UPDATE와 같은 문(통칭 "쓰기 문")으로 시작됩니다. 읽기 트랜잭션이 활성화된 상태에서 쓰기 문이 실행되면, 가능한 경우 읽기 트랜잭션이 쓰기 트랜잭션으로 업그레이드됩니다. 다른 데이터베이스 연결이 이미 데이터베이스를 수정했거나 수정하는 중이라면, 쓰기 트랜잭션으로의 업그레이드는 불가능하며 쓰기 문은 SQLITE_BUSY 오류와 함께 실패합니다.

읽기 트랜잭션이 활성화되어 있는 동안, 별도의 데이터베이스 연결에 의해 구현된 데이터베이스 변경 사항은 읽기 트랜잭션을 시작한 데이터베이스 연결에서 볼 수 없습니다. 데이터베이스 연결 X가 읽기 트랜잭션을 보유하고 있는 동안, 다른 데이터베이스 연결 Y가 X의 트랜잭션이 아직 열려 있는 동안 데이터베이스 내용을 변경할 수 있지만, X는 해당 트랜잭션이 종료될 때까지 그 변경 사항을 볼 수 없습니다. 읽기 트랜잭션이 활성화되어 있는 동안 X는 Y가 구현한 변경 이전의 데이터베이스의 과거 스냅샷을 계속 보게 됩니다.

2.2. DEFERRED, IMMEDIATE 및 EXCLUSIVE 트랜잭션

트랜잭션은 DEFERRED, IMMEDIATE 또는 EXCLUSIVE일 수 있습니다. 기본 트랜잭션 동작은 DEFERRED입니다.

DEFERRED는 데이터베이스에 처음 접근할 때까지 실제로 트랜잭션이 시작되지 않음을 의미합니다. 내부적으로 BEGIN DEFERRED 문은 데이터베이스 연결에 플래그를 설정하여, 마지막 문이 끝날 때 일반적으로 발생하는 자동 커밋을 끕니다. 이로 인해 자동으로 시작된 트랜잭션이 명시적인 COMMIT 또는 ROLLBACK이 있거나, 오류나 ON CONFLICT ROLLBACK 절에 의해 롤백이 유발될 때까지 유지됩니다. BEGIN DEFERRED 이후 첫 번째 문이 SELECT이면 읽기 트랜잭션이 시작됩니다. 이후의 쓰기 문은 가능한 경우 트랜잭션을 쓰기 트랜잭션으로 업그레이드하거나 SQLITE_BUSY를 반환합니다. BEGIN DEFERRED 이후 첫 번째 문이 쓰기 문이면 쓰기 트랜잭션이 시작됩니다.

IMMEDIATE는 데이터베이스 연결이 쓰기 문을 기다리지 않고 즉시 새 쓰기 트랜잭션을 시작하게 합니다. BEGIN IMMEDIATE는 다른 데이터베이스 연결에서 다른 쓰기 트랜잭션이 이미 활성화되어 있으면 SQLITE_BUSY로 실패할 수 있습니다.

EXCLUSIVE는 쓰기 트랜잭션이 즉시 시작된다는 점에서 IMMEDIATE와 유사합니다. EXCLUSIVE와 IMMEDIATE는 WAL 모드에서는 동일하지만, 다른 저널링 모드에서는 EXCLUSIVE가 트랜잭션 진행 중에 다른 데이터베이스 연결이 데이터베이스를 읽지 못하게 합니다.

2.3. 암시적 트랜잭션과 명시적 트랜잭션

암시적 트랜잭션(BEGIN으로 시작된 트랜잭션이 아니라 자동으로 시작된 트랜잭션)은 마지막 활성 문이 끝나면 자동으로 커밋됩니다. 문은 마지막 커서가 닫힐 때 끝나며, 이는 준비된 문이 재설정(reset)되거나 최종화(finalize)될 때 반드시 발생합니다. 일부 문은 재설정이나 최종화 이전에 트랜잭션 제어 목적으로 '끝난' 것으로 간주될 수 있지만, 이는 보장되지 않습니다. 문이 '끝났는지' 확인하는 유일한 방법은 해당 문에 sqlite3_reset() 또는 sqlite3_finalize()를 호출하는 것입니다. 증분 BLOB I/O에 사용되는 열린 sqlite3_blob도 끝나지 않은 문으로 간주됩니다. sqlite3_blob은 닫힐 때 끝납니다.

명시적 COMMIT 명령은 보류 중인 SELECT 문이 있어도 즉시 실행됩니다. 그러나 보류 중인 쓰기 작업이 있으면 COMMIT 명령은 SQLITE_BUSY 오류 코드로 실패합니다.

다른 스레드나 프로세스에 열린 읽기 연결이 있는 경우 COMMIT 실행 시도도 SQLITE_BUSY 반환 코드를 초래할 수 있습니다. 이렇게 COMMIT가 실패하면 트랜잭션은 계속 활성 상태로 유지되며, 읽기 측이 정리될 기회를 가진 후 COMMIT를 나중에 다시 시도할 수 있습니다.

아주 오래된 SQLite 버전(버전 3.7.11 - 2012-03-20 이전)에서는 보류 중인 쿼리가 있으면 ROLLBACK이 SQLITE_BUSY 오류 코드로 실패합니다. 더 최신 버전의 SQLite에서는 ROLLBACK이 진행되며 보류 중인 문은 종종 중단되어 SQLITE_ABORT 또는 SQLITE_ABORT_ROLLBACK 오류를 반환합니다. SQLite 버전 3.8.8(2015-01-16) 이상에서는 ROLLBACK이 데이터베이스 스키마를 수정하지 않는 한, 보류 중인 읽기는 ROLLBACK 이후에도 계속 작동합니다.

PRAGMA journal_mode가 OFF로 설정되면(즉, 롤백 저널 파일이 비활성화됨) ROLLBACK 명령의 동작은 정의되지 않습니다.

3. 트랜잭션 내 오류에 대한 응답

특정 종류의 오류가 트랜잭션 내에서 발생하면 트랜잭션이 자동으로 롤백될 수도 있고 그렇지 않을 수도 있습니다. 자동 롤백을 유발할 수 있는 오류는 다음과 같습니다.

  • SQLITE_FULL: 데이터베이스 또는 디스크가 가득 참
  • SQLITE_IOERR: 디스크 I/O 오류
  • SQLITE_INTERRUPT: sqlite3_interrupt() 또는 유사한 방법으로 작업이 중단됨
  • SQLITE_NOMEM: 메모리 부족

이 모든 오류에 대해 SQLite는 현재 작업 중이던 문 하나만 되돌리고, 같은 트랜잭션 내 이전 문들의 변경 사항은 그대로 유지한 채 트랜잭션을 계속 진행하려고 시도합니다. 그러나 평가 중인 문과 오류가 발생한 지점에 따라 SQLite가 전체 트랜잭션을 롤백하고 취소해야 할 수도 있습니다. 애플리케이션은 sqlite3_get_autocommit() 또는 sqlite3_txn_state() C 언어 인터페이스를 사용하여 SQLite가 어떤 조치를 취했는지 알 수 있습니다.

애플리케이션은 위에 나열된 오류에 명시적으로 ROLLBACK 명령을 실행하여 대응하고자 할 수 있습니다. 그렇게 하면 위 오류 중 하나가 발생한 후 트랜잭션 상태는 항상 동일합니다. 오류 응답으로 트랜잭션이 이미 자동 롤백된 경우 ROLLBACK 명령은 오류와 함께 실패하지만, 그로 인한 해로운 영향은 없습니다.

향후 SQLite 버전에서는 자동 트랜잭션 롤백을 유발할 수 있는 오류 목록이 확장될 수 있습니다. 향후 SQLite 버전에서는 오류 응답이 변경될 수 있습니다. 특히, 위 오류가 무조건적인 롤백을 강제하도록 하여 향후 SQLite 버전에서 인터페이스를 단순화할 수도 있습니다.

이 페이지는 2026-02-18 11:56:50Z에 마지막으로 업데이트되었습니다.

더 알아보기 (Learn more)