SQLite에서의 트랜잭션과 가상 테이블
(misfra.me)-
SQLite 가상 테이블도 쓰기 및 트랜잭션 지원이 가능하며,
xUpdate
,xSync
,xCommit
,xRollback
등의 훅을 구현해 사용함 - SQLite는 기본적으로 롤백 저널 방식으로 원자성을 보장하며, 여러 DB 파일을 다룰 때는 슈퍼 저널로 전체 커밋을 조정함
-
가상 테이블도 SQLite의 트랜잭션 프로토콜에 포함되어,
xSync
실패 시 전체 트랜잭션을 롤백함 - 커밋은 2단계로 나뉘며,
xSync
는 실패 가능성 있는 작업,xCommit
은 단순 정리 작업만 수행해야 함 -
xCommit
과xRollback
은 항상 호출될 수 있으므로 실패 없이 실행 가능한 정리용 함수로 작성해야 함
SQLite의 가상 테이블과 트랜잭션 처리
이전 글에서는 Go 언어를 통해 SQLite의 가상 테이블을 등록하고 쿼리하는 기본 방법을 소개했음. 이번 글에서는 쓰기 가능하고 트랜잭션을 지원하는 가상 테이블 구현법을 다룸.
가상 테이블의 쓰기 및 트랜잭션 지원
-
SQLite의 가상 테이블 인터페이스는 읽기 전용이 아님
-
xUpdate
훅을 구현하면 외부 데이터 소스에도 쓰기 가능 -
진정한 트랜잭션 일관성을 위해서는 다음과 같은 트랜잭션 훅 필요:
-
xBegin
: 트랜잭션 시작 알림 -
xSync
: 디스크에 안전하게 커밋하기 위한 준비 (여기서 실패하면 전체 롤백) -
xCommit
: 최종 커밋 및 정리 -
xRollback
: 트랜잭션이 중단됐을 경우 롤백 수행
-
-
일반 테이블 또는 다른 가상 테이블과 함께 수정될 때도 SQLite는 모든 훅을 연동해 원자성을 보장함
SQLite 트랜잭션의 내부 동작 방식
롤백 저널 (Rollback Journals)
- SQLite는 기본적으로 페이지를 덮어쓰기 전에 백업 파일(저널)에 저장
- 문제가 생기면 저널에서 복구하여 원자성 보장
참고: SQLite는 WAL 모드도 지원하지만 이 글의 범위에서는 제외됨
슈퍼 저널 (Super-Journals)
-
여러 데이터베이스가 연결된 경우, 각 DB에 개별 저널만으로는 동기화 어려움
-
슈퍼 저널이라는 상위 레벨 파일을 통해 여러 파일 간 커밋을 조정
-
한 DB 파일 내 여러 가상 테이블만 다루는 경우는 슈퍼 저널 없이도 동기화 가능
-
어떤 경우든 SQLite는 트랜잭션 흐름 안에서
xSync
,xCommit
,xRollback
훅을 자동으로 호출
가상 테이블과 함께하는 2단계 커밋
SQLite의 커밋 과정은 2단계로 이루어짐:
1단계: xSync
(Durability 보장)
- 모든 B-Tree 및 DB 파일의 페이지 또는 저널을 디스크에 안전하게 동기화
- 가상 테이블도 각각
xSync
훅이 호출됨 -
어느 한
xSync
에서 실패하면 전체 트랜잭션이 롤백됨 → 원자성 유지
2단계: 정리 (xCommit
)
-
디스크에 저장이 완료되면 저널 파일을 삭제하고 가상 테이블 정리 수행
-
아래는
vdbeaux.c
코드 일부임disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ sqlite3BtreeCommitPhaseTwo(pBt, 1); } } sqlite3EndBenignMalloc(); enable_simulated_io_errors(); sqlite3VtabCommit(db);
-
sqlite3VtabCommit()
안에서 실제로는 모든xCommit
호출이 실패해도 무시됨 → 순수한 정리 단계int sqlite3VtabCommit(sqlite3 *db){ callFinaliser(db, offsetof(sqlite3_module,xCommit)); return SQLITE_OK; }
-
xSync
로 내구성이 확보됐기 때문에,xCommit
,xRollback
은 실패해도 무시됨
가상 테이블 작성자를 위한 주의사항
-
지속성 있는 작업은 반드시
xSync
에 넣어야 함- 네트워크 I/O, 파일 쓰기 등 실패할 수 있는 작업은 여기서 처리해야 트랜잭션이 안전하게 중단됨
-
xSync
후에도xRollback
이 호출될 수 있음- 다른 테이블의
xSync
가 실패하면 전체 롤백됨
- 다른 테이블의
-
xCommit
과xRollback
은 실패하지 않는 정리용 함수로 작성- **idempotent(항등성)**하게, 여러 번 호출돼도 상태 변화가 없어야 함
결론
- SQLite의 저널링 메커니즘은 기본 테이블과 가상 테이블을 포함한 모든 요소의 원자성 커밋을 보장
- 가상 테이블의 트랜잭션 훅은 SQLite 트랜잭션 흐름에 자연스럽게 통합됨
- 가상 테이블을 구현하는 개발자는
xSync
에 집중하여 데이터 무결성을 확보하고, 정리 작업은xCommit
,xRollback
으로 나눠야 함