본문 바로가기
프로그래밍 놀이터/Database

[Database] -journal 파일의 정체는 뭘까? ( + WAL, temp files )

by 돼지왕 왕돼지 2019. 1. 15.
반응형

[Database] -journal 파일의 정체는 뭘까? ( + WAL, temp files )


http://gywn.net/2013/08/let-me-intorduce-sqlite/

http://www.sqlite.org/tempfiles.html

atomic commit rollback, CLOSE, COMMIT, compound select, constraint violation, db attach, db connection, db journal, Delete, disk rollback, distinct, except, exclusive, exclusive locking mode, group by, header zeroing, hot journal, intersect, journal, journal mode, last connection, linux wal limit, master journal, materializing, materializing subquery, Memory, memory share, mmap, None, off, Order by, persist, pragma journal_mode, pragma locking_mode, Query Optimizer, random name, rollback, rollback journal, shared lock, shared memory block, shared memory file, shm, SQLite, statement journal, subquery, temp db, temp files, temp files ), temp journal, temp table, transaction, transaction crash, transaction power off, transient indices, trsnaction, TRUNCATE, union, update insert, VFS, wal, wal log commit, wal mode, wal performance, wal vs journal, wal vs journal performance, write ahead to log, write read, [Database] -journal 파일의 정체는 뭘까? ( + WAL


Journal


-

-journal 은 rollback journal 이다.

이는 SQLite 에서 atomic commit & rollback 을 지원하기 위한 임시 파일이다.

<originalDBFileName>-journal 의 파일명을 갖는다.


rollback journal 은 보통 transaction 이 시작될 때 생성이 되고, 보통 transaction 이 commit 또는 rollback 으로 끝날 때 삭제된다.



-

보통 이 journal 파일은 SQLite DB 가 open 되었을 때, 좀 더 구체적으로 transaction 이 있을 때만 생성된다.

PRAGMA journal_mode 를 통해 journal 파일의 생성을 컨트롤 할 수도 있는데 기본값은 사용이 끝난 journal 은 삭제된다.

( 만약 PRAGMA locking_mode=EXCLUSIVE; 명령을 통해 exclusive locking mode 로 작동을 하면 journal 파일을 지우지 않고 SQL 버전에 따라 truncate 시키거나 header 를 zeroing 시킨다. )



-

데이터 변경이 발생하면..

1. 원본 데이터를 별도의 파일(journal 파일)에 저장

2. 데이터 변경

3. 백업 데이터 제거 (Commit or Rollback)



-

이 rollback.journal 은 예기치 않은 DB 에러에도 데이터 유실 혹은 파일 손상을 방지하기 위해, 문제 발생 시 원래 데이터로 복원하고자 하는데 목적이 있다.

만약 transaction 도중 crash 나 power off 가 발생한다면 disk 에 rollback 파일은 남아있는다. 다음번에 앱이 DB 를 open 하려 할 때 버려진 (정상적으로 종료되지 않은) journal 파일을 발견하고 ( 이를 hot journal 이라 부른다 ) 이를 이용해서 transaction 이 발생하기 전 DB 로 복구를 한다.



-

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


1. DELETE (default)

    rollback journal 파일을 매번 생성/삭제한다.


2. TRUNCATE

    rollback journal 파일을 매번 생성/삭제하지 않고, 파일 사이즈만 0으로 설정 후 재활용


3. MEMORY

    rollback journal 을 파일이 아닌 메모리에 유지한다. SQLite 를 사용하는 앱 장애시 데이터가 유실된다.


4. PERSIST

    rollback journal 을 지우지 않는다. 그러나 header 를 zeroing 한다 ( Exclusive locking mode 와 비슷한 동작 )


5. NONE ( OFF )

    rollback journal 을 사용하지 않고 DB 파일에 직접 기록한다. ( 문제 발생 시 복원 불가 )

    rollback 이라는 기능도 사용할 수 없다


6. WAL

    3.7.0 부터 가능한 녀석으로 log 에 해당 내용을 기록해놓고 한번에 commit 된다.



-

저널 파일이 생기는 시점에는 다른 프로세스에서 데이터를 읽을 수 있는 SHARED LOCK 이 걸리고, 실제적으로 데이터를 Writing 하는 과정에서는 Read 요청도 제한하는 EXCLUSIVE LOCK 이 잡힌다.


SQLite 는 DB 단위로 Lock 을 잡기 때문에 EXCLUSIVE LOCK 이 잡히면 다른 동작 요청은 Lock 이 풀릴 때까지 대기를 한다.

따라서 성능 이슈가 나올 수 있다.






WAL


-

3.7.0 에는 WAL ( Write Ahead to Log ) 방식이 새로 도입되었다.

이 녀석도 journal 과 마찬가지로 atomic commit 과 rollback 을 지원하기 위함이다.

이 녀석은 <originalDBFileName>-wal 형태를 갖는다.



-

WAL file 은 DB connection 이 처음 이뤄질 때 생성되고, last connection 이 close 될 때 제거된다.

그러나 예외상황이 발생하면 (정상종료하지 않으면) WAL 파일은 남게 되고, 다음에 DB open 시 이 정보를 이용해 DB 를 원상복구 한다.



-

모든 process 의 SQLite DB connection 은 memory share 가 필요한다.

WAL mode 에서는 WAL file 의 index 로 사용하는 share memory 공유가 필요하며 mmap() 으로 구현된 shared-memory file 이 쓰인다.

이 파일은 <originalDBFileName>-shm 의 파일명을 가지며, WAL mode 로 동작할 때에만 존재한다. 그래서 file 의 life time 도 동일하다.


shared-memory file 은 multi process 가 WAL mode 로 DB 를 접근할 때 shared memory block 을 제공하기 위한 목적으로만 쓰인다.

VFS 가 shared memory 에 접근하는 대체방법을 제공하면 이 파일 대신 그 방법이 쓰일 수 있다.

예를 들어 PRAGMA locking_mode=EXCLUSIVE 라면 (한 process 만 DB 에 접근할 수 있다) shared memory 는 heap 에 할당되고 shm 파일은 생성되지 않는다.



-

WAL 은 쓰기 요청이 들어오면 먼저 변경 사항을 WAL-Log 파일에 기록한다.

로그에 기록하는 것은 파일에 직접 기록하는 것보다 훨씬 빠르고 가벼운 요청이다.

그리고 WAL-Log 파일이 1000Page(Default)가 넘으면 일괄 commit 한다.

( 리눅스는 1Page = 4K 정도 되므로 대략 4MB 에 일괄 commit 한다. )


읽기 요청은 현재의 로그 파일과 DB 파일을 참조하여 처리한다.

기존의 DB 에서 direct 로 읽는 방식보다 성능이 약간 떨어질 수 있지만, 일반적으로 성능 차이가 거의 없다고 봐도 무관하다고 한다.

Write 와 Read 를 섞어 성능 테스트해보면 WAL 이 journal mode 보다 퍼포먼스가 좋게 나온다 한다.




기타


-

한 db connection 이 여러 DB 에 대해 single transaction 을 수행할 때 ( ATTACH 를 이용 ) 생기는 journal file 이 master journal 이다.

이 파일은 main db 와 같은 폴더에 생기며 suffix 는 일정하지 않다.



-

Statement journal 파일은 큰 transaction 에서 일부분만 rollback 하기 위해 사용된다.

예를 들어 UPDATE statement 가 100 개의 row 를 업데이트하는 경우, 50개를 modify 한 후 constraint violation 이 발생했을 경우 첫 50개의 change 를 rollback 하기 위해 사용된다.


그래서 statement jorunal 은 UPDATE 나 INSERT 에서만 생성되며, random name 으로 생성된다.



-

Temp table 은 이를 수행한 DB connection 에만 보이는 table 이다. ( 이 temp db 는 해당 db connection 이 close 될 때 자동 삭제된다. )

이 temp table 과 관련된 index, trigger, view 등은 별도의 temp db 에 저장된다.

이 temp db 도 rollback journal 이 필요하다.



-

subquery 가 있는 경우 그 결과를 temp table 에 저장해놓아야만 한다. 이를 materializing subquery 라고 부른다.

SQLite 의 query optimizer 는 materializing 을 피하려고 한다.

그러나 피할 수 없는 경우 temp table 이 각각의 temp file 에 저장되고, query 가 종료되면 삭제된다.



-

SQLite 는 다음 case 에 "transient indices” 를 사용한다.

    ORDER BY, GROUP BY clause 사용

    DISTINCT keyword 사용

    UNION, EXCEPT, INTERSECT 와 같은 compound SELECT 가 함께 수행


이 transient index 는 각각의 temp file 에 저장되며, statement 가 종료될 때 자동으로 삭제된다.




반응형

댓글