Sqlite

  • SQLite는 트랜잭션을 제공해주는 파일 기반의 DBMS이다.
  • 일반적인 DBMS처럼 데몬처럼 동작하는 방식이 아닌, 마치 라이브러리와 같이 프로그램에 직접 Embed하여 사용한다.
  • 프로그램 내부에서 잦은 파일접근을 최대한으로 적게하자는 취지로 만들어진 DB이다.

오늘 알아볼 내용은 SQL 데이터베이스에서 동시에 읽고 쓰는 상황에 대해서 알아볼 예정이다. 예를 들어 백그라운드의 데이터를 트랜잭션과 동기화하고 사용자가 동시에 UI에서 데이터를 탐색 할 수 있도록 허용해야 한다. 단일 쓰기 스레드다중 읽기 스레드 를 동시에 갖는 방법을 알아보자. (두 개 이상의 스레드에서 동시에 쓰는 것은 허용되지 않는다.)

트랜잭션에 쓸 때 읽을 수 없는 이유

  • 결론부터 말하자면 locking 때문이다.
  • 다른게 말하면 **rollback journal** mode 이다.
  • 이러한 것들은 트랜잭션에서 원자적(atomic) 커밋 및 롤백을 보장하는 메커니즘이다.
  • 동작 원리
    1. 스레드가 데이터베이스에 쓰려는 경우 동시 읽기 또는 쓰기를 방지하기 위해 EXCLUSIVE 잠금으로 데이터베이스 파일을 잠근다.
    2. 그런 다음 변경사항을 기본 데이터베이스 파일에 직접 기록하고 원본 레코드를 롤백 저널로 이동한다.
    3. 커밋시 기본 데이터베이스 파일이 이미 수정되었으므로 SQLite는 롤백 저널 파일만 삭제하고 트랜잭션은 유지된다.
    4. 롤백의 경우 롤백 저널의 모든 레코드가 주 파일로 다시 복원된다. 1

WAL 모드로 전환

  • 병렬 읽기 및 쓰기를 할때의 해결책은 journal modeWrite-Ahead Log 로 바꾼다.
  • WAL은 rollback journal 을 반대로 한다.
  • 단순히 WAL 파일에 변경 사항을 쓰고 나중에 기본 데이터베이스 파일로 이동한다.
  • 이러한 작업은 자동으로 수행되며 checkpointing 이라고 한다.
  • WAL 모드에서는 다른 사람이 Write-Ahead log에 쓰는 동안 누구나 메인 데이터베이스 파일에서 읽을 수 있다. 2

Write-Ahead log는 중간중간에 많은 트랜잭션이 나타날 수 있다.

예를 들어, 커밋이라는 트랜잭션이 발생한다면 커밋은 단순히 WAL 파일에 다른 레코드로 기록된다.

다른 스레드가 데이터베이스에서 읽기를 원할 때 WAL 파일의 마지막 커밋 레코드를 기억하고 그 뒤에 있는 모든 것을 무시한다. 3

SQLite 코드

## journal mode 변경
sqlite> pragma journal_mode = WAL;

번외

SQLite에서 journal mode는 총 6가지가 있다.

  1. DELETE (Default)

    Rollback Journal File을 매번 Create/Delete

  2. TRUNCATE

    Rollback Journal을 매번 Create/Delete하지 않고, 파일 사이즈만 0으로 설정 후 재활용

  3. MEMORY

    저널링 파일을 메모리에서 유지, SQLite를 사용하는 어플리케이션에서 장애 시 데이터 유실

  4. PERSIST

    저널링 파일을 지우지 않음

  5. NONE

    데이터 파일을 직접 기록(문제 발생 시 데이터 복원 불가)

sqlite> pragma journal_mode = TRUNCATE;