← 전체 글로 돌아가기

DB

SQLite WAL 파일을 모르고 백업했다가 복구가 어긋난 날

작은 서비스 DB를 파일 하나만 복사했다가 최근 데이터가 빠진 경험과 백업 기준을 정리했다.

복구했는데 마지막 글이 없었다

작은 서비스라서 SQLite 파일 하나만 백업하면 충분하다고 생각했다. 새 서버에서 app.db를 복사해 띄웠더니 대부분의 데이터는 있었지만 방금 작성한 몇 개의 행이 빠져 있었다. 처음에는 내가 잘못된 백업 파일을 고른 줄 알았다.

확인해 보니 운영 DB는 WAL 모드였다. 이 모드에서는 변경 내용 일부가 app.db-wal 파일에 남아 있을 수 있다. 나는 app.db만 복사했고, 그래서 복구본이 최신 상태가 아니었다.

현재 모드 확인

SQLite 셸에서 저널 모드를 확인했다.

sqlite3 app.db 'PRAGMA journal_mode;'

결과가 wal이면 관련 파일을 같이 고려해야 한다.

ls -lh app.db app.db-wal app.db-shm

여기서 헷갈린 점은 app.db의 수정 시간이 최신이 아니어도 서비스는 정상적으로 최신 데이터를 보여 줄 수 있다는 것이다. 최신 변경분이 WAL에 있기 때문이다.

백업 전에 한 일

서비스가 쓰기 작업을 하지 않는 시간대를 골라 DB 관련 파일을 한 세트로 보관했다.

mkdir -p /backup/sqlite
cp app.db app.db-wal app.db-shm /backup/sqlite/

다운타임을 피하고 싶을 때는 SQLite의 백업 기능을 쓰는 쪽이 안전했다.

sqlite3 app.db ".backup '/backup/sqlite/app-$(date +%F).db'"

복구 테스트까지 포함하면 아래처럼 최소한의 무결성 검사를 돌렸다.

sqlite3 /backup/sqlite/app-2026-07-07.db 'PRAGMA integrity_check;'
sqlite3 /backup/sqlite/app-2026-07-07.db 'select count(*) from posts;'

지금 쓰는 백업 기준

내 기준은 이렇게 바뀌었다.

  • SQLite 파일 하나만 복사하지 않는다
  • WAL 모드인지 먼저 확인한다
  • 가능하면 .backup 명령으로 일관된 스냅샷을 만든다
  • 백업 파일 크기만 보지 말고 row count를 확인한다
  • 한 달에 한 번은 빈 서버에서 실제 복구를 해 본다

짧은 회고

백업은 파일을 만드는 일이 아니라 다시 살릴 수 있는 상태를 만드는 일이라는 걸 다시 느꼈다. 특히 SQLite는 간단해서 방심하기 쉬운데, WAL을 쓰는 순간 백업 방식도 같이 정해야 한다.