VPS 운영 환경에서 SQLite 사용하기: 설정 및 주의사항
소규모 웹 애플리케이션을 위한 SQLite 운영 가이드입니다. WAL 모드 설정과 busy_timeout 최적화, Litestream을 활용한 데이터 백업 방법을 다룹니다. 단일 VPS 환경에서 SQLite가 적합한 이유와 확장 시 발생하는 한계점을 명확히 정리했습니다.
VPS에서 SQLite가 적합한 운영 데이터베이스인 경우
대부분의 소규모 애플리케이션에서 VPS 환경의 운영 데이터베이스로 SQLite를 사용하는 것은 올바른 선택입니다. 이유는 간단합니다. 한 대의 머신에서 하나의 프로세스가 하나의 파일에 기록하는 방식은 별도의 데이터베이스 서버를 필요로 하지 않기 때문입니다. 관리해야 할 데몬도, 방화벽으로 막아야 할 포트도, 주기적으로 변경해야 할 비밀번호도, 가동 상태를 유지해야 할 두 번째 머신도 없습니다. 쿼리는 네트워크 왕복이 아닌 함수 호출로 처리되므로, 40개의 쿼리를 실행하는 페이지는 40번의 함수 호출 비용만 발생합니다.
물론 제약 사항은 명확하고 실질적입니다. SQLite는 전체 데이터베이스 파일에 대해 한 번에 하나의 쓰기 작업만 허용하며, 파일을 두 머신 간에 공유할 수 없습니다. 이 두 가지 제한은 단일 애플리케이션을 실행하는 단일 VPS 환경에서는 문제가 되지 않습니다. 하지만 이 규모를 벗어나는 순간 두 제한은 치명적인 장애 요인이 됩니다. 이 가이드에서는 서버에서 SQLite를 안전하게 사용하기 위한 설정, Litestream을 이용한 지속적 백업, 그리고 SQLite 사용을 중단해야 할 시점에 대해 다룹니다.
먼저 명령줄 도구를 설치합니다. 아래의 모든 내용은 Ubuntu 24.04 환경에서 실행되었습니다.
sudo apt update
sudo apt install -y sqlite3
sqlite3 --version이 명령을 실행하면 3.로 시작하는 버전 정보와 빌드 날짜, 소스 해시가 출력됩니다. 2026년 7월 기준 Ubuntu 24.04는 SQLite 3.45.1 버전을 제공합니다. 애플리케이션은 이 바이너리를 직접 사용하지 않을 가능성이 높습니다. 대부분의 언어 런타임은 자체적으로 SQLite 라이브러리를 내장하고 있으며, 종종 더 최신 버전을 포함하기도 합니다. 따라서 최신 기능을 사용하기 전에 데이터베이스 드라이버가 보고하는 버전을 먼저 확인하십시오.
WAL 모드를 가장 먼저 변경해야 하는 이유
기본적으로 SQLite는 롤백 저널을 사용합니다. 페이지를 변경하기 전에 원본 페이지를 -journal 파일로 복사한 다음, 데이터베이스를 직접 수정합니다. 이를 안전하게 처리하기 위해 전체 파일에 대해 배타적 잠금을 수행하므로, 쓰기 작업이 진행되는 동안 모든 읽기 작업은 대기해야 합니다. 노트북 환경에서는 이를 체감하기 어렵지만, 웹 서버에서는 느린 쓰기 작업 하나가 데이터베이스를 참조하는 모든 요청을 지연시킵니다.
WAL(write-ahead log) 모드는 이 순서를 뒤집습니다. 쓰기 작업은 새로운 페이지를 별도의 -wal 파일에 추가하고 메인 데이터베이스는 그대로 둡니다. 읽기 작업은 시작 시점의 스냅샷을 기준으로 메인 파일을 계속 읽으므로, 읽기 작업이 쓰기 작업을 차단하지 않으며 쓰기 작업 또한 읽기 작업을 차단하지 않습니다. 이후 체크포인트(checkpoint) 과정을 통해 누적된 WAL 페이지를 메인 데이터베이스로 다시 병합합니다. 이 설정 하나만으로도 SQLite를 웹 애플리케이션의 백엔드로 사용하기에 충분한 성능을 확보할 수 있습니다.
WAL 모드 활성화 및 적용 확인
mkdir -p ~/app
sqlite3 ~/app/app.db "PRAGMA journal_mode=WAL;"이 명령은 wal을 출력합니다. 이 출력은 단순한 장식이 아닙니다. PRAGMA journal_mode는 데이터베이스가 현재 실제로 어떤 모드인지 반환하므로, delete이라는 응답이 나온다면 변경에 실패했으며 여전히 롤백 저널 모드임을 의미합니다.
WAL 모드는 영구적입니다. 이는 연결 설정이 아니라 데이터베이스 헤더에 기록되는 플래그이므로, 데이터베이스 파일당 한 번만 실행하면 이후의 모든 연결은 재부팅 후를 포함하여 해당 설정을 상속받습니다. 새로운 연결을 통해 이를 확인해 봅니다.
sqlite3 ~/app/app.db "PRAGMA journal_mode;"이제 테이블을 생성하고 디스크에 어떤 파일이 나타나는지 확인합니다.
sqlite3 ~/app/app.db <<'SQL'
CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, body TEXT NOT NULL);
INSERT INTO notes (body) VALUES ('first row');
SQL
ls -l ~/app/이제 app.db, app.db-wal, app.db-shm 세 개의 파일이 존재합니다. -wal 파일은 아직 체크포인트되지 않은 커밋된 페이지들을 담고 있습니다. -shm 파일은 모든 연결이 공유 메모리 인덱스로 매핑하여 WAL에 무엇이 포함되어 있는지 일치시키는 역할을 합니다. 두 파일 모두 데이터베이스의 일부이며 임시 파일이 아닙니다. 애플리케이션이 실행 중인 상태에서 app.db만 단독으로 복사하면 최근 커밋이 모두 누락된 파일을 얻게 됩니다. app.db을 삭제하고 나머지 두 파일을 그대로 두면, SQLite는 해당 이름으로 새로 나타나는 파일에 오래된 WAL 페이지들을 적용합니다. 이것이 바로 데이터베이스를 초기화하려다 오히려 손상시키는 흔한 원인입니다.
모든 프로덕션 애플리케이션에 필요한 연결 설정
데이터베이스에는 journal_mode만 저장됩니다. 아래의 다른 모든 설정은 연결별로 적용되므로, 애플리케이션이 여는 각 연결마다 이를 실행해야 합니다. 여기에는 연결 풀이 백그라운드에서 생성하는 모든 연결이 포함됩니다.
PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 5000;
PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = ON;busy_timeout = 5000는 SQLite가 잠긴 데이터베이스에 대해 database is locked을 반환하기 전까지 최대 5000밀리초 동안 재시도를 수행하도록 지시합니다. 기본값은 0이므로, 두 쓰기 작업이 겹칠 경우 SQLite는 기본적으로 즉시 실패합니다. 이 단일 값을 설정하는 것만으로도 SQLite 자체의 문제로 간주되던 대부분의 잠금 오류가 해결됩니다.
synchronous = NORMAL은 WAL 모드에서 적절한 설정이며, 그에 따른 트레이드오프를 이해할 필요가 있습니다. FULL에서 SQLite는 모든 커밋마다 WAL에 대해 fsync를 호출합니다. NORMAL에서는 체크포인트 시점에 동기화를 수행합니다. SQLite 문서에서는 이 설정으로 인해 포기해야 하는 점을 명확히 밝히고 있습니다. 즉, 전원 차단이나 강제 재부팅 후에는 트랜잭션의 영속성이 보장되지 않습니다. 전원 손실로 인해 데이터베이스가 손상되지는 않지만, 디스크에 기록되지 않은 마지막 커밋들은 유실됩니다. VPS 환경에서는 모든 쓰기 작업마다 발생하는 fsync를 제거할 수 있으므로, 일반적으로 이 트레이드오프가 적절한 선택입니다.
foreign_keys = ON는 하위 호환성을 위해 기본적으로 꺼져 있으며, 연결별로 적용됩니다. REFERENCES 절이 가득 찬 스키마라 하더라도 각 연결에서 이 설정을 켜지 않으면 아무것도 강제되지 않습니다.
나중에 고려해야 할 설정이 하나 더 있습니다. SQLite는 WAL 파일이 1000페이지를 넘어서면 자동으로 체크포인트를 수행하며, 이 작업은 해당 시점에 트랜잭션을 완료하는 연결이 담당하게 됩니다. 이는 그 자체로 문제가 되지 않습니다. 하지만 Litestream을 실행 중일 때는 체크포인트 시점을 Litestream이 제어하기를 원하므로 문제가 될 수 있습니다.
busy_timeout을 설정했는데도 database is locked이 발생하는 이유
이 오류는 사용자가 다시 Postgres로 돌아가게 만드는 원인이며, 명확한 이유가 하나 있습니다.
busy timeout은 busy handler를 설치하지만, SQLite는 이를 반드시 호출하겠다고 보장하지 않습니다.
SQLite가 busy handler를 호출하면 교착 상태(deadlock)가 발생할 수 있다고 판단하면, busy handler를 호출하는 대신 애플리케이션에 즉시 SQLITE_BUSY를 반환합니다.
이러한 교착 상태는 트랜잭션이 업그레이드될 때 발생합니다. SQLite에서 단순히 BEGIN만 사용하면 BEGIN DEFERRED을 의미합니다. 그 뒤에 오는 첫 번째 문장이 SELECT라면, 현재 읽기 트랜잭션 상태입니다. 같은 트랜잭션 내에서 나중에 UPDATE이 발생하여 쓰기 트랜잭션으로 전환해야 하는데, 읽기를 시작한 이후 다른 연결이 이미 데이터를 썼다면 SQLite는 대기할 수 없습니다. 이미 스냅샷이 구버전이 되었기 때문에 대기하면 두 연결이 서로 교착 상태에 빠지기 때문입니다. 문서에는 그 결과가 명시되어 있습니다.
이후의 쓰기 문장은 가능하면 트랜잭션을 쓰기 트랜잭션으로 업그레이드하거나, SQLITE_BUSY를 반환합니다.
5000밀리초의 타임아웃은 고려 대상조차 되지 않습니다. 오류가 즉시 발생하므로 설정이 아무런 효과가 없는 것처럼 보입니다.
해결책은 한 단어입니다.
BEGIN IMMEDIATE;
UPDATE notes SET body = 'edited' WHERE id = 1;
COMMIT;BEGIN IMMEDIATE은 아무것도 읽기 전에 시작부터 쓰기 잠금을 획득합니다. 업그레이드 과정이 없으므로 피해야 할 교착 상태도 없으며, 따라서 busy handler가 적용되어 연결이 실패하는 대신 순서를 기다리게 됩니다. 읽기 전용 트랜잭션은 deferred로 유지하십시오. 쓰기 작업이 포함된 모든 트랜잭션은 immediate여야 합니다.
잠금 오류의 두 번째 원인은 파악하기 더 어렵습니다. 느린 작업이 진행되는 동안 쓰기 트랜잭션을 열어두는 경우입니다. SQLite는 쓰기 작업을 직렬화하므로, 트랜잭션을 열고 네트워크를 통해 외부 API를 호출한 뒤 커밋하는 작업은 해당 호출 시간만큼 다른 모든 쓰기 작업을 차단합니다. 필요한 데이터를 읽고 트랜잭션을 닫은 뒤, 느린 작업을 수행하고, 마지막으로 짧은 쓰기 트랜잭션을 열어 결과를 저장하십시오.
Litestream을 이용한 지속적 백업
매일 밤 수행하는 복사는 최대 하루치 쓰기 작업을 유실할 수 있으며, 실행 중인 SQLite 데이터베이스에 cp를 실행하면 열리지 않는 복사본이 생성될 수 있습니다. 안전한 방법은 두 가지입니다. sqlite3 app.db ".backup /path/to/backup.db"은 SQLite의 온라인 백업 인터페이스를 사용하므로 사용 중인 데이터베이스에서도 정상적으로 작동합니다. Litestream은 여기서 더 나아가 WAL을 감시하고 변경 사항을 객체 스토리지로 지속적으로 전송합니다. 이를 통해 최악의 경우 데이터 유실 범위를 하루에서 약 1초 수준으로 줄일 수 있습니다.
Litestream은 애플리케이션 옆에서 실행되는 단일 Go 바이너리입니다. 애플리케이션과 데이터베이스 사이에 위치하지 않습니다. 애플리케이션은 이전과 동일하게 SQLite에 직접 쓰기를 수행하며, Litestream은 WAL을 읽어 변경된 내용을 업로드합니다.
cd /tmp
curl -fsSL -O https://github.com/benbjohnson/litestream/releases/download/v0.5.14/litestream-0.5.14-linux-x86_64.deb
sudo dpkg -i litestream-0.5.14-linux-x86_64.deb
litestream versionv0.5.14는 2026년 7월 기준 공식 Linux 설치 페이지에 문서화된 릴리스이며, 2026년 7월 21일에 v0.5.15가 출시되었습니다. 릴리스 페이지의 최신 태그에 맞춰 두 줄의 버전을 수정하십시오. 만약 사용 중인 VPS가 arm64 아키텍처라면 해당 arm64 패키지를 선택하십시오.
설정 파일은 /etc/litestream.yml에 위치합니다. 클라우드 자격 증명 없이도 전체 루프를 검증할 수 있도록 로컬 파일 복제본부터 시작하십시오.
dbs:
- path: /home/appuser/app/app.db
replica:
type: file
path: /var/backups/litestream/app필드 이름이 단수형인 replica라는 점에 유의하십시오. Litestream 0.5 버전부터는 0.3 시리즈의 replicas 배열이 단일 복제본 블록으로 대체되었습니다. 따라서 두 개의 항목이 포함된 설정 파일은 시작 시 실패합니다. 많은 타사 가이드가 여전히 이전 배열 방식을 보여주고 있으므로, 검색 결과의 첫 번째 예시보다는 위의 형식을 복사하십시오. 또한 0.5 시리즈에서는 디스크 내 백업 형식이 변경됨에 따라 litestream wal 하위 명령이 litestream ltx로 이름이 변경되었습니다.
기능을 활성화하기 전에 설정 파일이 정상적으로 파싱되는지 확인하십시오.
sudo litestream databases -config /etc/litestream.yml그런 다음 수동으로 왕복 복제를 검증하십시오. 이 방식은 설정 파일을 건너뛰고 하나의 데이터베이스를 하나의 경로로 복제합니다.
mkdir -p /tmp/replica
litestream replicate ~/app/app.db file:///tmp/replica/app이 명령은 포그라운드에서 계속 실행됩니다. 두 번째 셸에서 행을 하나 작성한 뒤, 복제본을 새로운 파일로 복원하십시오.
sqlite3 ~/app/app.db "INSERT INTO notes (body) VALUES ('written after replication started');"
litestream restore -o /tmp/restored.db file:///tmp/replica/app
sqlite3 /tmp/restored.db "SELECT count(*) FROM notes;"행 개수에 새로운 행이 포함되어야 합니다. 만약 포함되지 않았다면 변경 사항이 아직 동기화되지 않은 것입니다. Litestream은 기본값이 1초인 sync-interval 주기로 푸시를 수행하므로, 잠시 기다린 후 다시 복원하십시오. 이 1초라는 시간이 곧 복구 시점(RPO)이 됩니다. 시스템이 충돌하더라도 마지막 동기화 간격 이후의 쓰기 작업만 유실되며, 어떤 설정을 하더라도 이 유실 범위를 0으로 만들 수는 없습니다.
실제 스토리지에 저장하려면 복제본 블록을 S3 URL로 교체하십시오. 이는 Amazon S3뿐만 아니라 다른 제공업체의 S3 호환 객체 스토리지에서도 작동합니다.
dbs:
- path: /home/appuser/app/app.db
replica:
url: s3://your-bucket-name/app
region: us-east-1
snapshot:
interval: 24h
retention: 24h자격 증명 정보를 설정 파일에 직접 넣지 마십시오. Litestream은 환경 변수에서 LITESTREAM_ACCESS_KEY_ID 및 LITESTREAM_SECRET_ACCESS_KEY을 읽어오므로, root 소유의 600 모드로 설정된 systemd 드롭인 파일에 저장하십시오.
위의 스냅샷 값은 기본값이며, 보존 기간(retention) 기본값은 사용자들을 당황하게 할 수 있습니다. 보존 기간은 Litestream이 스냅샷과 그에 속한 파일들을 유지하는 기간이며, 이는 곧 과거의 어느 시점까지 복구할 수 있는지를 결정합니다. 24시간으로 설정하면 수요일 아침에 발견한 잘못된 마이그레이션은 월요일 상태로 복구할 수 없습니다. retention: 168h를 일주일로 설정하고 추가 스토리지 비용을 지불하는 것을 권장합니다.
복구가 필요한 상황이 오기 전에 복구 과정을 검증하십시오
litestream restore -o /tmp/check.db /home/appuser/app/app.db
sqlite3 /tmp/check.db "PRAGMA integrity_check;"
sqlite3 /tmp/check.db "SELECT count(*) FROM notes;"데이터베이스 경로가 주어지면, litestream restore은 /etc/litestream.yml에서 일치하는 복제본을 찾아 내려받습니다. PRAGMA integrity_check는 정상적인 파일일 경우 ok을 출력하며, 다른 결과가 출력된다면 복구된 사본을 사용할 수 없다는 의미입니다. 이 과정을 systemd 서비스 및 타이머를 사용하여 주기적으로 실행하고 출력 내용을 확인하십시오. 백업을 실제로 한 번이라도 복구해 보기 전까지는 해당 백업이 정상적으로 작동하는지 알 수 없습니다.
systemd에서 Litestream 실행하기
Debian 패키지는 /etc/litestream.yml을 읽어 들이는 litestream 유닛을 설치합니다.
sudo systemctl enable litestream
sudo systemctl start litestream
sudo journalctl -u litestream -f정상적인 출력은 설정 파일에 명시된 각 데이터베이스의 이름을 나열한 뒤, 주기적인 동기화 로그 외에는 조용히 유지됩니다. 데이터베이스 경로에 대해 no such file or directory 오류가 발생한다면 설정 파일의 경로가 잘못되었거나 프로세스가 해당 경로를 읽을 수 없음을 의미합니다. 기본적으로 이 유닛은 root 권한으로 실행되는데, 이는 이 작업에 필요한 것보다 과도한 권한입니다. Litestream은 데이터베이스 파일뿐만 아니라 해당 데이터베이스가 위치한 디렉터리도 읽고 쓸 수 있어야 합니다. 이는 데이터베이스 옆에 생성되는 -wal 및 -shm 파일을 다루기 때문이므로, 애플리케이션이 이미 사용 중인 계정을 할당하십시오.
# /etc/systemd/system/litestream.service.d/override.conf
[Service]
User=appuser
Group=appusersudo systemctl daemon-reload와 sudo systemctl restart litestream을 사용하여 적용하십시오. 최소 권한을 가진 전용 서비스 계정을 설정하는 데는 몇 분 정도 소요되지만, 이는 단순한 백업 에이전트와 서버 내의 두 번째 root 프로세스라는 큰 차이를 만듭니다.
시스템을 처음부터 다시 구축하는 경우 한 가지 순서상의 세부 사항이 중요합니다. 애플리케이션이 시작되기 전에 데이터베이스가 복원되어야 합니다. litestream restore는 -if-db-not-exists를 지원하며, 파일이 이미 존재할 경우 0을 반환하고 종료되므로 매 부팅 시 실행해도 안전합니다. 애플리케이션 유닛의 ExecStartPre 라인에 이를 추가하면, 새로운 VPS는 데이터베이스를 내려받고 기존 VPS는 아무 작업도 수행하지 않게 됩니다. 설정을 한곳에서 관리하고 싶다면 litestream replicate의 -restore-if-db-not-exists 플래그를 사용할 수도 있습니다.
VPS에서 SQLite가 작동하지 않는 경우
네트워크 파일 시스템. 이는 설정을 변경해도 해결할 수 없는 한계입니다. WAL 모드는 데이터베이스를 사용하는 모든 프로세스가 작은 메모리 영역을 공유해야 하며, 이 역할을 -shm 파일이 수행합니다. SQLite 문서에는 다음과 같은 규칙이 명시되어 있습니다.
데이터베이스를 사용하는 모든 프로세스는 동일한 호스트 컴퓨터에 있어야 합니다. WAL은 네트워크 파일 시스템에서 작동하지 않습니다.
따라서 마운트된 NFS(network file system)나 SMB 공유에 있는 데이터베이스는 손상될 수 있으며, 이를 방지할 수 있는 pragma는 없습니다. 여기서 사람들이 간과하는 차이점이 있습니다. 대부분의 VPS 제공업체가 추가 저장소로 연결하는 네트워크 블록 장치는 Linux에서 일반적인 파일 시스템을 가진 일반 디스크로 인식되므로 문제가 없습니다. 하지만 마운트된 파일 공유는 그렇지 않습니다.
두 번째 애플리케이션 서버. 이를 가능하게 하는 설정은 없습니다. 두 대의 머신에서 동일한 데이터를 서비스해야 하는 시점이 오면, 네트워크를 통해 통신하는 데이터베이스가 필요합니다. 계획을 세울 시간이 있을 때 이 전환을 결정하십시오.
쓰기 작업이 많은 워크로드. 한 번에 한 명의 작성자만 허용하는 것은 파일 형식의 특성이며, 조정 가능한 설정이 아닙니다. 각 커밋은 WAL에 추가되는 방식이므로 짧은 쓰기 작업은 비용이 적게 듭니다. 따라서 처리량은 CPU보다 디스크의 작은 쓰기 지연 시간에 더 큰 영향을 받습니다. 그 차이에 대해서는 VPS에서 NVMe와 SATA SSD 저장소 비교를 참조하십시오. 긴 트랜잭션은 다른 모든 작성자를 대기열에 세우기 때문에 실제적인 문제가 됩니다.
분석 쿼리. SQLite는 트랜잭션을 위해 구축된 행 기반 저장소입니다. 1억 개의 행을 스캔하는 대시보드는 다른 도구가 필요한 다른 작업이며, 서버 작업에서 DuckDB와 SQLite 비교에서 그 경계가 어디인지 다룹니다.
복제 중 VACUUM. 전체 VACUUM은 데이터베이스 파일 전체를 다시 작성합니다. 이는 Litestream이 전체 파일을 다시 업로드해야 함을 의미하며, Litestream 문서는 복제가 활성화된 상태에서 이를 실행하지 말 것을 권장합니다. 복제기를 중지하고, vacuum을 수행한 뒤, 다시 시작하십시오. 이후 새로운 전체 스냅샷이 생성될 것입니다.
하나의 데이터베이스에 두 개의 복제기. 동일한 데이터베이스나 동일한 복제 대상에 대해 두 개의 Litestream 프로세스를 절대 실행하지 마십시오. 이를 방지하는 것은 사용자의 책임이라는 점이 문서에 명확히 명시되어 있으며, 이를 어길 경우 복구할 수 없는 복제본이 생성됩니다.
Litestream이 다루지 않는 범위
Litestream은 오직 데이터베이스 파일만 보호합니다. 업로드된 파일, 애플리케이션 설정, TLS(전송 계층 보안) 인증서, unit 파일은 모두 사용자가 직접 관리해야 합니다. restic을 사용한 외부 암호화 백업을 일정에 맞춰 병행하면 두 영역 모두 안전하게 보호할 수 있습니다. 서버를 새로 설정하는 경우, 새 VPS에서의 초기 10분 가이드를 참고하여 이 문서에서 이미 완료된 것으로 간주하는 사용자 계정 생성 및 방화벽 설정을 진행하십시오.
FAQ
SQLite는 프로덕션 애플리케이션에 적합합니까?
단일 서버에서 운영하는 단일 애플리케이션이라면 적합합니다. 단, WAL 모드를 활성화하고, busy timeout을 설정하며, 지속적으로 백업을 수행해야 합니다. 고려해야 할 구조적 제한 사항은 한 번에 하나의 쓰기 작업만 가능하다는 점과 단일 호스트 머신에서만 동작한다는 점입니다. 이러한 제한 내에서 운영 가능한 애플리케이션이라면 네트워크 홉이나 별도의 모니터링 프로세스 없이 데이터베이스를 사용할 수 있습니다. 이 범위를 벗어나는 애플리케이션은 클라이언트-서버 방식의 데이터베이스가 필요하며, 어떤 튜닝으로도 이 구조적 한계를 극복할 수는 없습니다.
busy_timeout을 설정했는데도 왜 여전히 database is locked 오류가 발생합니까?
대기 상태가 데드락을 유발할 수 있는 경우 SQLite가 busy handler를 건너뛰기 때문입니다. 일반적인 BEGIN으로 시작하는 트랜잭션은 지연(deferred) 처리됩니다. 즉, 처음에 SELECT를 실행하면 읽기 트랜잭션으로 진입하고, 이후 쓰기 작업 시 잠금 업그레이드가 필요합니다. 만약 그 사이에 다른 연결이 쓰기를 수행했다면, 읽기 스냅샷이 이미 유효하지 않게 되므로 SQLite는 busy handler를 호출하는 대신 즉시 SQLITE_BUSY를 반환합니다. 쓰기가 포함된 트랜잭션은 시작할 때 BEGIN IMMEDIATE을 사용하여 쓰기 잠금을 미리 확보해야 timeout 설정이 정상적으로 적용됩니다.
SQLite 데이터베이스를 네트워크 스토리지에 저장해도 됩니까?
NFS나 SMB와 같은 네트워크 파일 시스템에서는 사용할 수 없습니다. WAL 모드는 모든 프로세스가 -shm 파일을 통해 메모리를 공유해야 하며, SQLite 문서에 따르면 데이터베이스를 사용하는 모든 프로세스는 반드시 동일한 호스트 컴퓨터에 있어야 합니다. 단, 제공업체에서 연결한 네트워크 블록 장치는 다릅니다. 이 경우 리눅스는 일반적인 디스크와 파일 시스템으로 인식하므로 SQLite가 정상적으로 작동합니다.
이미 매일 밤 백업을 수행하고 있는데도 Litestream이 필요합니까?
얼마만큼의 데이터 손실을 감수할 수 있는지에 따라 다릅니다. 매일 밤 수행하는 작업은 최대 24시간 분량의 쓰기 데이터를 잃을 수 있음을 의미합니다. Litestream은 초당 약 1회 동기화를 수행하므로, 장애 발생 시 마지막 1초 정도의 데이터만 손실됩니다. 또한, 쓰기 도중의 데이터베이스 상태를 복사할 위험이 있는 cp 명령어를 사용하는 것보다 훨씬 안전합니다. Litestream은 데이터베이스만 다루므로, 일반적인 파일 백업도 병행하여 유지하는 것이 좋습니다.