[Database] -journal 파일의 정체는 뭘까? ( + WAL, temp files ) |
http://gywn.net/2013/08/let-me-intorduce-sqlite/
http://www.sqlite.org/tempfiles.html
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 가 종료될 때 자동으로 삭제된다.
'프로그래밍 놀이터 > Database' 카테고리의 다른 글
[SQLite] GLOB vs. LIKE (0) | 2019.01.19 |
---|---|
[Sqlite] 1802 error 의 정체는? (0) | 2018.12.18 |
[SQLite3] Appendix. SQLite3 커맨드 라인 도구, 관리도구 (0) | 2018.05.26 |
[SQLite3] 09. 안드로이드와 데이터베이스 (0) | 2018.05.25 |
[SQLite3] 06. 임베디드 SQLite3 최적화 #2 (0) | 2018.05.23 |
댓글