SQLite에서 기본을 넘어선 저널

발행: (2026년 1월 16일 오전 04:38 GMT+9)
11 min read
원문: Dev.to

Source: Dev.to

번역할 텍스트를 제공해 주시면, 해당 내용을 한국어로 번역해 드리겠습니다.

소개

안녕하세요, 저는 마네시와르입니다. 저는 현재 FreeDevTools online을 구축하고 있습니다 – 모든 개발자 도구, 치트 코드, TL;DR을 한 곳에 모아 놓은 무료 오픈‑소스 허브입니다. 이제 웹을 끝없이 검색할 필요가 없습니다!

어제

우리는 rollback journals – 사전 이미지, 세그먼트, 헤더, 그리고 SQLite가 데이터베이스 파일을 손상시키지 않고도 충돌을 견딜 수 있는 이유를 탐구했습니다.

오늘

두 가지 덜 알려졌지만 중요한 구성 요소를 다룸으로써 legacy journaling 그림을 완성합니다:

  1. Statement journal – 단일 실패 문장을 롤백합니다.
  2. Master journal – 다중 데이터베이스 트랜잭션을 조정합니다.

이들은 함께 SQLite가 충돌뿐만 아니라 문장 실패다중 데이터베이스 커밋에서도 정확성을 보장하는 방식을 보여줍니다. 이는 storage + journaling 장을 마무리합니다.

내일

우리는 transaction management and locking으로 한 단계 올라갑니다.


Source:

Statement Journal – Rolling Back a Single Statement

Statement journal는 한 가지 매우 구체적인 이유 때문에 존재합니다:

중간에 실패한 단일 SQL 문장의 부분적인 효과를 취소하기 위해.

INSERT, UPDATE, DELETE가 여러 행을 건드리다가 제약 조건 위반이나 트리거 예외로 문장이 중단될 때 발생합니다. 이때 주변 사용자 트랜잭션은 계속 활성 상태를 유지해야 하고, 문제를 일으킨 문장만 롤백되어야 합니다. 바로 여기서 statement journal이 역할을 합니다.

Statement Journal이 무엇이고, 무엇이 아닌가

✅ 무엇인가❌ 무엇이 아닌가
별도의 롤백‑저널 파일충돌 복구에 사용되지 않음
임시 파일(예: etilqs_*와 같은 무작위 이름)으로 저장세그먼트 헤더가 없음
시스템 임시 디렉터리(예: /tmp)에 존재체크섬이 없음
문장 실행 중에만 존재충돌 후에도 지속되지 않음
문장이 끝나면 즉시 삭제모든 메타데이터(예: nRec, 시작 시 DB 크기)는 메모리에 보관되고 디스크에 기록되지 않음

Statement Journal 수명 주기

핵심 아이디어: SQLite는 주변 사용자 트랜잭션을 중단하지 않고 단일 문장을 롤백할 수 있다.

Statement‑journal lifecycle diagram

SAVEPOINT와의 상호 작용

SAVEPOINT는 중첩 레이어를 추가합니다:

  • 중첩된 savepoint를 지원하기 위해, SQLite는 해당 savepoint가 해제되거나 외부 트랜잭션이 커밋될 때까지 statement journal을 보존합니다.
  • 이 설계는 세밀한 롤백 의미론을 제공하면서도 사용자에게는 API를 단순하게 유지합니다.

다중 데이터베이스 트랜잭션과 원자성 문제

SQLite는 하나의 연결에 여러 데이터베이스를 첨부할 수 있습니다:

ATTACH 'db2.sqlite' AS db2;

이제 단일 트랜잭션이 main, db2 또는 다른 첨부된 데이터베이스를 수정할 수 있습니다. 각 첨부된 데이터베이스는 자신만의 롤백 저널을 가지고 독립적으로 커밋합니다. 조정이 없으면 트랜잭션의 “전부 혹은 전무” 보장인 원자성이 깨집니다.

마스터 저널 – 원자적 커밋 조정

데이터베이스 간 원자성을 유지하기 위해 SQLite는 트랜잭션에 관여하는 모든 개별 롤백 저널의 이름을 기록하는 마스터 저널을 생성합니다. 커밋 과정은 다음과 같습니다:

  1. 마스터 저널을 기록 (모든 자식 저널을 나열).
  2. 마스터 저널을 디스크에 플러시.
  3. 각 첨부된 데이터베이스의 개별 저널을 커밋.
  4. 모든 커밋이 성공하면 마스터 저널을 삭제.

어떤 단계에서든 실패하면 SQLite는 마스터 저널에 저장된 정보를 사용해 모든 데이터베이스를 롤백할 수 있어 트랜잭션이 진정으로 원자적임을 보장합니다.

결과: 많은 첨부 데이터베이스가 있더라도 트랜잭션은 완전히 성공하거나 완전히 롤백되어 데이터 무결성을 유지합니다.

시각적 요약

다중 DB 트랜잭션 다이어그램


TL;DR

FeaturePurposePersistence
Statement journal단일 실패 문장을 주변 트랜잭션을 중단하지 않고 롤백일시적인 메모리 내 메타데이터; 문장 실행 후 삭제
Master journal여러 연결된 데이터베이스에 걸친 원자적 커밋 보장전체 트랜잭션이 커밋되거나 롤백될 때까지 영구 보관

Working with Multiple Databases, Transactions, and SQLite Internals

Athreya (aka Maneshwar) • Jan 6

Tags: #webdev #programming #database #architecture

The Master Journal: Coordinating Child Journals

멀티‑DB 트랜잭션을 전역적으로 원자적으로 만들기 위해 SQLite는 master journal을 도입합니다.

Important Properties

  • Created only when committing – deleted once the commit finishes.
  • Never created for transaction aborts.
  • Contains no page images – it stores only the names of child rollback journals.

각 트랜잭션에 참여하는 롤백 저널은 child journal이 됩니다.

Master Journal File

  • 주 데이터베이스와 같은 디렉터리에 존재합니다.
  • 파일명 형식: -mj (무작위 접미사가 이름 충돌을 방지).

What the Master Journal Contains

master journal은 전체 UTF‑8 경로모든 child rollback journal의 이름과 함께 NUL (\0) 문자로 구분하여 저장합니다. 페이지 데이터는 없고, 단지 조정 메타데이터만 포함합니다.

How Child Journals Reference the Master Journal

커밋 시점에 각 child rollback journal은 섹터 경계에 기록되는 master‑journal 레코드를 추가합니다. 레코드에는 다음이 들어갑니다:

  1. master‑journal 이름의 길이.
  2. 이름의 체크섬.
  3. 이름 자체 (UTF‑8).
  4. 금지된 페이지 번호 (lock‑byte 페이지).

이 양방향 연결은 복구 과정에서의 정확성을 보장합니다.

Child journal record layout

Why the Master Journal Exists

SQLite가 커밋 중에 충돌하면 복구는 다음과 같이 진행됩니다:

  • 각 child journal을 검사합니다.
  • child journal은 master journal을 가리키며, 이는 어떤 저널들이 함께 묶여 있는지 알려줍니다.
  • 모든 child journal이 안전하게 커밋될 때 비로소 트랜잭션이 완료된 것으로 간주됩니다.

따라서 master journal은 데이터베이스 간 전역 원자성을 유지합니다.

Forbidden Page Number (Lock‑Byte Page)

각 master‑journal 레코드에는 lock‑byte 페이지를 가리키는 금지된 페이지 번호가 포함됩니다. 이 페이지는:

  • 예약되어 있으며 절대 쓰여지지 않습니다.
  • Windows와 POSIX 파일 잠금 방식의 차이를 처리하기 위해 존재합니다.
  • SQLite는 의도적으로 이 페이지를 건드리지 않습니다.

Legacy Journaling Architecture (Big Picture)

Journal TypePurpose
RollbackCrash recovery
StatementSingle‑statement rollback
MasterMulti‑DB atomicity

Journaling architecture diagram

Summary

  • SQLite는 고정 크기 페이지로 구성된 하나의 파일에 데이터와 메타데이터를 모두 저장합니다.
  • 페이지 1은 데이터베이스를 고정하고 전역 메타데이터를 보관합니다.
  • 사용되지 않은 페이지는 freelist를 통해 추적됩니다.
  • 레거시 저널링은 세 가지 저널 타입을 사용합니다: rollback, statement, 그리고 master.
    • Rollback journal은 충돌 안전성을 보장합니다.
    • Statement journal은 문장 수준의 정확성을 보장합니다.
    • Master journal은 데이터베이스 간 전역 원자성을 보장합니다.

스토리지와 저널링 이야기는 여기까지입니다.

다음 주제: 런타임 동작 – 트랜잭션 종류, 잠금 모드, 그리고 shared, reserved, exclusive 잠금의 구분. “디스크상의 바이트”에서 “메모리상의 동시성”으로 넘어갑니다.

My SQLite experiments and hands‑on examples live here:
lovestaco/sqlite – sqlite‑examples

References

  • SQLite Database System: Design and Implementation – Sibsankar Haldar.
  • FreeDevTools – 유용한 개발 도구 모음.

👉 FreeDevTools 확인해 보세요:

피드백이나 기여를 환영합니다!
⭐ GitHub에서 프로젝트에 ⭐ 별표를 달아 주세요.

Back to Blog

관련 글

더 보기 »

SQLite 내부: 파일 이름 지정

이 장은 SQLite의 가장 낮은 수준까지 모두 확대합니다—디스크상의 바이트가 페이지가 되고, 페이지가 트리가 되며, 내구성이 저널링을 통해 보장됩니다.

데이터베이스 트랜잭션 누수

소개 우리는 memory leaks에 대해 자주 이야기하지만, backend development에서 또 다른 조용한 성능 저해 요인이 있습니다: Database Transaction Leaks. 나는 최근에 ...

LeetCode 1193 해결 방법

문제 설명 테이블 **Transactions**는 다음과 같은 열을 가지고 있습니다: - id (primary key) - country - state (enumeration: 'approved' 또는 'declined') - amount - trans…