LLM WikiAccess-protected knowledge portal
← 스터디 홈
99편 · 약 11분

Turso v0.7: SQLite를 Rust로 다시 써서 동시 쓰기·전문 검색·벡터를 하나의 엔진에 통합한 방법

SQLite가 풀지 못한 세 가지 문제

SQLite는 임베디드 데이터베이스 중 단연 널리 쓰인다. 그러나 에이전트 시대의 워크로드 — 동시 쓰기가 빈번하고, 전문 검색과 벡터 검색이 함께 필요하며, I/O가 비동기여야 하는 — 에는 세 가지 벽에 부딪힌다.

  1. 단일 쓰기 잠금: 모든 쓰기가 WAL 파일의 배타적 잠금을 놓고 경쟁한다. 동시 쓰기 처리량이 직렬화된다.
  2. 동기 I/O: SQLite 코어는 동기 POSIX 호출 위에 세워졌다. async/await 런타임 위에서 사용하려면 별도 스레드 풀이 필요하다.
  3. 외부 확장 의존: 전문 검색(FTS5)은 별도 가상 테이블 확장이고, 벡터 검색은 sqlite-vec 같은 추가 로드가 필요하다.

Turso(tursodatabase/turso)는 이 세 문제를 해결하기 위해 SQLite를 처음부터 Rust로 다시 작성한 프로젝트다. v0.7.0에서 MVCC 동시 쓰기가 안정화되고, FTS·벡터 검색·시퀀스·ICU 콜레이션이 한 엔진에 통합됐다. 2026년 8월 3일에는 클라우드 환경 동시 쓰기 얼리 프리뷰가 공개됐다.

libSQL과 Turso DB: 두 개의 트랙

혼동하기 쉬운 부분이 있다. Turso 팀은 두 가지 데이터베이스를 유지한다.

  • libSQL: SQLite 소스를 C로 포크한 버전. 오늘의 Turso Cloud를 실제로 구동하는 프로덕션 엔진. sqlite3와 API 호환.
  • Turso Database (tursodatabase/turso): SQLite와 동일한 SQL 문법과 파일 형식을 지원하면서 내부 구현을 Rust로 전면 재작성한 프로젝트. v0.7.0부터 베타 경고가 공식 해제됐고, 복수의 조직에서 프로덕션 사용 중.

이 글은 Turso Database(Rust 재작성 버전)의 v0.7 변화를 다룬다.

MVCC와 BEGIN CONCURRENT

SQLite의 단일 쓰기 잠금을 해결하는 핵심 기술이 MVCC(Multi-Version Concurrency Control)다. Turso의 구현은 Microsoft SQL Server의 Hekaton 메모리 최적화 엔진(SIGMOD 2013)에서 착안했다.

동작 원리:

  • 쓰기 트랜잭션은 행 수준의 배타 잠금을 잡는 대신 새 버전을 생성한다.
  • 각 행의 버전 체인은 인메모리 인덱스로 추적된다. 읽기는 자신의 스냅샷 시점 이전 버전을 선택하므로 쓰기에 블록되지 않는다.
  • 충돌 감지는 커밋 시점에 행 단위로 이뤄진다. 서로 다른 행을 수정한 두 트랜잭션은 충돌 없이 모두 커밋된다.
  • BEGIN CONCURRENT 문으로 시작한 트랜잭션만 MVCC 경로를 탄다. 기존 BEGIN은 그대로 직렬 WAL을 사용한다.

v0.7에서는 MVCC 엔진의 쓰기 처리량이 대폭 향상됐고, 복구(recovery) 경로가 단순해졌으며, 여러 행 버전을 유지하는 인메모리 비용이 줄었다.

-- MVCC 경로: 여러 쓰기 트랜잭션이 충돌 없이 병렬 진행
BEGIN CONCURRENT;
UPDATE orders SET status = 'shipped' WHERE id = 42;
COMMIT;

-- sequence_watermark(): CDC 소비자가 안전하게 읽을 수 있는 최대 커서 값
SELECT sequence_watermark('my_sequence');

비동기 I/O: completion 기반 설계

SQLite는 I/O를 동기 POSIX 호출로 처리한다. Turso는 설계 단계부터 completion 기반 비동기 I/O를 채택했다.

VDBE(가상 머신) 인스트럭션이나 B-트리 커서가 버퍼 풀에 없는 페이지를 필요로 하면 IOResult::IO를 반환하고 실행 스레드를 블록하지 않고 제어권을 양보한다. JavaScript 바인딩에서는 이 신호가 STEP_IO 상수로 노출돼 이벤트 루프가 다른 작업을 처리하거나 I/O 완료를 기다린다.

Linux에서는 io_uring을 백엔드로 사용해 커널-유저스페이스 경계를 최소화한다. 호출 스레드가 차단되지 않으므로 단일 스레드에서도 높은 동시성이 가능하다.

Tantivy 기반 전문 검색 (FTS)

SQLite의 FTS5는 TF-IDF 변형 방식의 랭킹을 제공하지만 별도 가상 테이블 확장이다. Turso는 Tantivy를 내장해 완전히 새로운 FTS 레이어를 구축했다.

Tantivy는 Apache Lucene 방식의 역색인 라이브러리(Rust 구현)로 BM25 랭킹을 기본 제공한다.

-- FTS 인덱스 생성 (index_method 실험적 기능 활성화 필요)
CREATE INDEX docs_fts ON docs USING fts(title, body);

-- 세 가지 FTS 전용 함수
SELECT id, fts_score(docs_fts) AS score,
       fts_highlight(body, '<b>', '</b>') AS snippet
FROM docs
WHERE fts_match(docs_fts, 'database concurrent writes')
ORDER BY score DESC
LIMIT 10;
  • fts_match(): BM25 매칭 필터
  • fts_score(): 관련도 점수
  • fts_highlight(): 매칭 구간 강조

기존 FTS5 기반 코드는 CREATE VIRTUAL TABLE이 아닌 CREATE INDEX ... USING fts 구문으로 전환해야 한다.

내장 벡터 검색

별도 확장 없이 벡터 열을 선언하고 ANN(Approximate Nearest Neighbor) 인덱스를 생성할 수 있다.

CREATE TABLE embeddings (
    id     INTEGER PRIMARY KEY,
    doc_id INTEGER,
    vec    FLOAT32[1536]   -- OpenAI text-embedding-3-small 차원
);

CREATE INDEX emb_idx ON embeddings USING vector(vec);

-- 코사인 유사도 기반 k-NN 검색
SELECT e.id, e.doc_id,
       vector_distance_cos(e.vec, ?) AS dist
FROM embeddings e
ORDER BY dist
LIMIT 5;

임베딩과 문서 데이터를 하나의 SQLite 호환 파일에 저장하므로 별도 벡터 DB 운영 부담이 없다. RAG 파이프라인에서 임베딩 저장 계층을 단순화할 때 유용하다.

PostgreSQL 스타일 시퀀스

AUTOINCREMENT가 동시 쓰기 환경에서 예측 불가하게 동작하는 문제를 해결하기 위해 독립적인 시퀀스 오브젝트가 도입됐다.

CREATE SEQUENCE order_seq START 1000 INCREMENT 5;

INSERT INTO orders (id, item)
VALUES (nextval('order_seq'), 'widget');

-- sequence_watermark(): 이 값 이하의 id는 CDC 소비자가 안전하게 읽을 수 있음
SELECT sequence_watermark('order_seq');

sequence_watermark()는 CDC(Change Data Capture) 소비자가 커서 기반 읽기를 할 때 아직 커밋되지 않은 레코드를 건너뛰지 않도록 안전한 상한선을 제공한다.

ICU 콜레이션

텍스트를 로케일에 맞게 정렬하는 ICU_COLLATION 지원이 추가됐다.

-- 한국어 로케일, 대소문자 무시, 억양 민감
CREATE TABLE kr_text (content TEXT COLLATE icu_ko_ci_as);
SELECT content FROM kr_text ORDER BY content COLLATE icu_ko_ci_as;

콜레이션 이름을 등록해 ORDER BY와 인덱스 어디서든 사용할 수 있다.

Turso v0.7 아키텍처 개요

SQL 클라이언트
SQLite 호환 SQL
libsql-client / JDBC / .NET 바인딩
MCP 서버 모드
에이전트 직접 연결
쿼리 엔진 (Rust)
VDBE 인터프리터
IOResult::IO 비블로킹 양보
MVCC 레이어
BEGIN CONCURRENT
Hekaton 스타일 행 버전 체인
커밋 시점 충돌 감지
B-트리 스토리지
SQLite 파일 형식 호환
검색·분석 레이어
Tantivy FTS
BM25 역색인
fts_match / fts_score / fts_highlight
벡터 인덱스
FLOAT32[N] 열 타입
ANN 근사 검색
코사인·L2 거리
시퀀스·ICU 콜레이션
sequence_watermark() CDC 지원
I/O 백엔드
io_uring (Linux)
completion 기반
스레드 비블로킹
동기 폴백
macOS / Windows
POSIX read/write
Turso v0.7 구성 요소 아키텍처

운영 현황과 한계

현재 상태(v0.7 기준):

  • Turso Database(Rust 재작성): 베타 경고 해제, 다수 조직 프로덕션 사용 중. 1.0 아님.
  • 클라우드 동시 쓰기(BEGIN CONCURRENT): 2026-08-03 얼리 프리뷰 공개. 로컬 임베디드는 이전부터 사용 가능.
  • libSQL(C 포크)은 여전히 Turso Cloud의 실제 프로덕션 엔진.

주의사항:

  • MVCC 충돌(동일 행 동시 수정)은 커밋 시점에 감지돼 오류를 반환한다. 재시도 로직이 필요하다.
  • 윈도 함수(Window Functions)는 v0.7에서 "준비 중" 상태다.
  • FTS 인덱스는 index_method 실험적 기능 플래그 활성화가 필요하다.
  • SQLite 고급 확장(json_each, FTS5 가상 테이블 구문 등) 일부가 아직 호환되지 않는다. COMPAT.md에서 지원 목록 확인.

SQLite에서 마이그레이션:

  • 기존 .db 파일은 Turso가 읽을 수 있다(파일 형식 호환).
  • CREATE VIRTUAL TABLE fts USING fts5(...)CREATE INDEX ... USING fts(...) 구문 변경 필요.
  • AUTOINCREMENT 의존 코드는 시퀀스로 단계적 전환 권장.

References