Architecture 중 WAL 에 대해 정리 하였습니다.
내용이 중복되는 내용도 있지만, 공식 문서에만 있는 수준의 정보도 있습니다. 쉽게 정리하는 것이 중요하지만, 이해를 못하더라도 연관 되는 내용이 반복되는 경우가 존재하기 때문에, 이런 내용도 있구나 하고 넘어 가는 것도 좋다고 생각합니다.
Postgresql Architecture
WAL 동작에 대한 간략한 이해도
-
세그먼트 파일은 단조 증가하는 파일 이름을 사용하고 가급적 많은 WAL 레코드를 포함
-
파일 크기는 구성 가능하며 기본값은 16MiB
-
크기 또는 개수 측면에서 대량 트랜잭션이 예상되는 경우 생성되는 세그먼트 파일의 총 수를 줄이고 파일 관리 부담을 줄이기 위해 더 큰 크기를 선택할 수 있습니다.
-
MongoDB Journal log (https://hyunki1019.tistory.com/155)
-
MySQL 은 WAL 전략을 채택하여 Redo Log Buffer에 transaction log 를 작성(redo log를 뜻함)
-
WAL Buffers 내용을 WAL Files에 기록
-
WAL Log / Transaction Log / Redo log
-
sync / async mode 존재
-
Segment file size : 16mb
-
Log file 로 분할된 segment 개수 64개 (wal_keep_segments -> Logical log file)
-
max_wal_size 만큼 생성 (64개 넘어가면 한개 삭제되고 한개 생성되는 형태 -> rotation 이 아님)
-
64*16 = 1024mb ( max_wal_size 1gb)
-
min_wal_size (80mb = 16*5 = 5개 생성되고 이후 한개 삭제, 한개 생성)
-
해당 File 를 이용하면 CDC 프로그램도 개발이 가능
-
pg_resetxlog
-
9.6 이하에서 사용하였으며, pg_resetwal 로 변경
-
WAL 파일을 reset 하는 명령어
-
pg_resetwal
-
WAL 초기화 진행 및 pg_control 파일에 저장된 일부 제어 정보도 초기화
-
서버가 crash 로 인해 손상되어 시작이 안될 때 강제 부팅하는 역할이 필요할때만 진행
-
데이터 일관성 문제 발생할 수 있으며, 별도 복구가 반드시 필요
-
-
- pg_switch_xlog()
- 강제로 WALog swiching
- pg_xlogdlump
- wal log 작성된 내용 확인
- pg_xlogdump ./000000001000000012341223 (WAL log file)
- 데이터 번호/ schema 번호 / 디비번호 형태로 결과
- 병목 현상
- block 단위로 WAL log 에 기록 다음 checkpoint 가 발생하기 전까지 레코드 단위로 WAL log 기록
- log size 늘리거나 디스크를 좋은 것 사용 외에는 해결 불가
- full_page_writes parameter 를 off 하여 속도 향상
- Vacuum freeze를 하면 XID frozen 작업으로 인해 레코드 변경이 발생
- 1bit 변경됐지만 full_page_writes 기능으로 인해 block 단위 redo가 생성
- block 단위로 WAL log 에 기록 다음 checkpoint 가 발생하기 전까지 레코드 단위로 WAL log 기록
-
-
모든 변경 기록을 보관(transaction log)
- 무결성을 보장하기 위한 작업
- Tip - Journaled file 은 불필요
- WAL 가 안정적으로 저장하기 때문에, Journaled file이 필요없음
- journal
- pg_journal 를 사용 하여 journal log에 직접 로그 메시지를 작성
- DB 활동을 기록하는 파일로, 문제 해결 및 성능 분석에 사용
- https://pgxn.org/dist/pg_journal/doc/pg_journal.html
- Journal 은 오버헤드로 인해 성능 저하를 유발(Disk flush / 단, ext3 일 경우 data=writeback 옵션을 사용하여 data flush 진행 시 발생할 수 있는 오버헤드를 줄일 수 있음)
- Journal 은 DB Crash 발생 시 부팅 속도를 향상할 수 있는 효과
- journal
- WAL 가 안정적으로 저장하기 때문에, Journaled file이 필요없음
-
복구를 위해 기록하는 것으로, DB가 crash 되었을 경우 check point 동작 전이라고 하면 디스크에 저장이 안되어 유실되는데, 이것을 방지하기 위해 WAL 로그를 읽어와 복구 진행
-
os buffer cache 영역에는 자주 요청되는 디스크 블록을 저장하지만, 이건 Disk 로 바로 write 되도록 postgresql 에서 강제로 할 수 있음.(wal_sync_method parameter 참고)
-
Disk 의 실제 페이지에 DML하기전에 주기적으로 전체 페이지 이미지를 WAL에 영구적으로 저장
-
그래서 Crash가 발생하더라도 WAL에서 부분적으로 작성된 페이지를 복원이 가능
-
WAL 파일의 각 레코드는 레코드 내용이 올바른지 확인할 수 있는 CRC-32(32bit)검사로 작성 및 보호 (복구 시 확인)
-
WAL 레코드에 기록된 전체 페이지 이미지는 보호되지만, 데이터 페이지는 기본적으로 chechsum 되지 않음
-
-
데이터만 WAL에 작성이 되고, 통계정보 관련된 각종 시스템 정보들은 저장되지 않고, 복구 진행 시 최근 변경사항으로 재구축-재설정 되도록 동작
-
Temptable 정보도 저장되지 않음
-
-
WAL 를 사용하면 Disk write 수가 줄어드는데, Transaction 에 의해 변경된 모든 데이터가 아닌, commit 보장하기 위한 WAL 파일만 disk 에 flush 하면 되기 때문 -> 데이터 페이지를 Flush 하는 비용보다 더 저렴
-
특히, 소규모 transaction 을 동시에 처리하는 시스템에서 WAL 파일의 fsync 하나만으로 많은 transaction을 commit 하는데 충분하기 때문
-
fsync (boolean)
-
fsync가 on이면, PostgreSQL서버는 fsync()시스템콜을 통해서 변경분을 디스크에 물리적으로 바로 쓴다. 이는 데이터베이스클러스터가 OS나 하드웨어 장애시 consistent한 상태로 복구가 가능함을 보장한다.
-
fsync를 off한다면, OS가 알아서 메모리에 있는 것을 디스크로 내려쓰게 된다. 언제 무엇이 디스크에 쓰여졌는지 아닌지 알수 없다. 그러므로 성능상 이득을 볼수는 있겠지만, 전원장애나 system crash로가 발생했을때 복구가 불가능할수 있다. 만약 전체 데이터베이스를 쉽게 재생성할수 있는 경우에만 off하도록 한다. 예를들어 백업본으로부터 새로운 데이터베이스 클러스트를 초기 구축하는 경우, 버리고 재생성할 데이터베이스의 데이터 처리, 자주 재생성되는 read-only 데이터베이스 복제본으로 failover에 사용되지 않는 데이터베이스인 경우 사용할 수 있다. 고성능의 하드웨어 장비라고해서 fsync를 끄는 것은 올바르지 않다.
-
성능을 위해서라면 synchronous_commit을 off하는 것만으로 충분할 것이다.
-
만약 off하기로 했다면, full_page_writes도 off하는 것을 고려하도록 한다.
-
-
WAL 를 사용하여, PITR 지원이 가능
-
WAL 를 재생하여 복구가 가능
-
-
Asynchronous Commit
-
DB Crash 발생 시, 가장 최근의 Transaction은 유실 가능성 존재(Risk)
-
다만, transaction 을 더 빠르게 처리가 가능
-
Default 는 synchronous (동기)
-
Client에 transaction result를 return 하기 전에, WAL 의 record가 Disk 에 write될 때까지 기다렸다가 ack 처리. -> commit 된 transaction 에 대한 무결성 보장을 의미
-
다만, 이것에 대한 비용은 발생
-
-
이러한 비용을 조금이라도 줄이기 위한 방법으로, disk flush 응답을 받기 전에 WAL buffer에서만 작성 후 ack 하는 방식을 Asynchronous Commit -> Transaction 처리량 향상
-
synchronous_commit Parameter 를 이용하여 수정이 가능하며, transaction 마다 설정이 가능
-
트랜잭션 커밋하기전에 WAL 레코드가 disk까지 쓰인다음에 success를 리턴할 것인가 여부
-
on : default
-
off : 클라이언트에 바로 transaction commit을 보냄. 하지만 실제로 트랜잭션이 안전하게 반영(WAL record가 WAL file에 쓰여짐) 되기까지 딜레이가 존재함. 서버 crash났을때 트랜잭션 손실될 수 있음. (최대 delay는 wal_writer_delay(200ms)의 3배). 하지만 fsync와는 달리 off로 한다고 해서 db 일관성에 문제가 되지는 않음. 최근 커밋되어야하는 트랜잭션이 손실될 수는 있으나 database 상태는 이 트랜잭션들이 정상적으로 롤백된 것과 같아서 일관성에 문제 없음.
-
-
DROP TABLE 은 synchronous_commit 와 상관없이 동기식으로 처리 : 일관성을 보장하기 위함.
-
PREPARE TRANSACTION 와 같은 2-phase commit 의 경우도 동기식으로 처리
-
wal_writer_delay ms 마다 WAL Writer 가 Disk 로 flush 진행
- 최대 유실 시간은 wal_writer_delay milliseconds * 3 의 risk 가 존재
- busy periods(바쁜기간?)에 WAL writer 가 한 번에 Disk 로 flush 를 진행하는 것을 선호로 인해 발생 (정확한 의미는 모르겠습니다. 왜 wal_writer_delay 의 최대 3배의 시간으로 명시했는지.
- 최대 유실 시간은 wal_writer_delay milliseconds * 3 의 risk 가 존재
- commit_delay parameter 와 유사하지만, commit_delay 는 synchronous commit 의 방법에 속함
-
Asynchronous commit 을 설정하면, commit_delay 는 무시
-
commit_delay 는 transaction 이 WAL disk flush 지연을 유발
-
-
- WAL Configuration
- 참고로 checkpoint 는 checkpoint 이전까지의 기록된 transaction 의 sequence 지점
-
checkpoint 를 기준으로 모든 Dirty data page가 Disk 로 flush 되고 특수 checkpoint record가 WAL 파일에 기록
-
DB Crash 가 발생하면, 최신 checkpoint 지점을 찾은 후, WAL 에서 시작해야 되는 시점을 찾아 복구 진행
-
최소 Checkpoint 지점까지는 Disk 에 있는 것을 보장되며, WAL 기준으로는 checkpoint 이전 파일은 필요 없으며, 이전 segment 또한 필요가 없음을 의미하고 재활용 되거나 제거할 수 있음을 의미
-
full_page_writes
-
Default on
-
checkpoint 이후 각 Disk page를 수정(dml로 인해) 하는 도중에 해당 페이지의 전체 내용을 WAL 에 기록
-
os crash 발생 시, 진행 중인 페이지 쓰기가 부분적으로만 완료 되어 디스크 상의 페이지에 과거 데이터와 새 데이터가 공존하기 때문에, 복구 진행 시 올바른 복구가 보장되지만 WAL 에 기록하는 데이터량은 증가될 수 밖에 없음
-
checkpoint 간격을 늘릴 수 있음.
-
- off 하면, 운영 속도가 향상되지만, 시스템 crash 발생 시, 손상된 데이터가 복구 불가능 또는 데이 손사이 발생 가능성 존재
-
fsync 를 해제했을 때와 유사
-
PITR 진행 시, WAL 아카이빙 사용에는 영향을 미치지 않음
-
postgresql.conf 파일 또는 command 로 설정 가능
-
-
- checkpoint_timeout sec 마다 또는 max_wal_size 가 초과될 경우 checkpoint 발생
-
default : 5 min (300 sec) / 1 Gb
-
WAL 에 작성이 안된 경우 checkpoint_timeout 이 되어도 checkpoint 가 발생하지 않음
-
물론 CHECKPOINT 명령어로 강제 실행은 가능
-
만약 해당 변수 값들을 줄이며, 더 자주 checkpoint 발생 : DB crash 후 빠른 복구는 가능하지만 Disk I/O 비용 발생
-
full_page_writes 가 설정된 경우 (default 설정) , check point 발생 후 데이터 페이지 수정이 발생하는 경우 전체 페이지가 기록 -> 더 많은 Disk I/O 발생(시간을 짧게 가져갈수록 disk I/O는 더욱더 증가)
-
checkpoint_timeout 시간을 충분히 여유있게 가져가는 것을 책에서는 권장하며, checkpoint_warning 로 checkpoint 에 대해 sanity check (온전성 검사?)가 가능
-
당연하겠지만, checkpoint timeout 보다 더 잦은 checkpoinrt 가 발생하면 max_wal_size 증가 하라는 메시지가 log 에 남음
-
- XLogInsertRecord
-
Shared memory 내 WAR buffer 에 new record 를 배치하는데 사용
-
만약 새로운 데이터가 insert 될 공간이 없으면, kernel cache 로 채워진 WAL buffer 일부를 move 시킴 -> 이것은 exclusive lock (대상 data page) 을 유발하기 때문에, 성능에 좋지 않음
-
일반적으로 XLogFlush 에 의해 WAL buffer 를 WAL file 에 flush 되어야 함.
-
wal_buffers 를 이용하여 WAL bufferpool 수를 조정 가능하며, full_page_writes 가 설정되어 있고, 시스템이 바쁜경우 wal_buffers 수를 늘려주는 것을 권장
-
- XLogFlush
-
LogWrite 의 issue_xlog_fsync 의 호출에 의해 XLogFlush 가 WAL buffer 의 내용을 disk 로 flush
-
commit_delay
-
commit_delay (ms)는 XLogFlush 내에서 lock 을 획득 하는동안, group commit 을 기다리는 시간(지연시간) parameter
-
목적은 동시에 commit 되는 transaction 전체에 걸쳐 flush 작업의 비용을 분할할 수 있는 것(다만 transaction 시간은 증가)
- commit_delay 가 발생하면, 대기하는 commit record들은 WAL Buffer 에 추가 하여 정합성을 지키는 효과 -> Transaction 대기 시간을 최소화
-
0 : ( default)그룹 커밋의 효과가 중요
-
1 : 동시에 commit 이 발생하여 transaction 처리?
-
2 : 처리량이 commit 속도에 따라 제한 되는 경우 도움 ?
-
-
-
wal_debug 를 활성화 하면, XLogInsertRecord, XLogFlush 의 call 횟수를 확인할 수 있음.
-
WAL 데이터를 Disk 에 Writer 하는 함수는 XLogWrite and issue_xlog_fsync 존재
-
WAL 데이터를 동기화하는 데 소요되는 시간은, pg_stat_wal 내의 wal_write_time and wal_sync_time 에 기록
-
wal_sync_method 가 open_sync 또는 open_datasync 이면, XLogWrite는 WAL 데이터를 Disk 로 flush 하고 데이터 정합성을 보장하고, issue_xlog_fsync 는 어떠한 작업도 하지 않음
-
wal_sync_method 가 fdatasync , fsync , 또는 fsync_writethrough 가 되면, write opertaion이 WAL buffer 를 kernal cache로 이동하고 issue_xlog_fsync 는 kernal cache 내용을 Disk로 동기화 진행
-
XLogWrite Write 및 issue_xlog_fsync 가 WAL 데이터를 disk 로 동기화하는 횟수가, pg_stat_wal 에서 wal_write 및 wal_sync 값으로 저장
-
- WAL Internal
-
WAL 는 rotation 하기 때문에, 관리자가 별도로 disk 관련하여 신경쓰지 않아도 됨
-
LSN 으로 어느 WAL 파일에 작성해야 하는지 (마지막 지점) 확인
-
WAL 파일은 Data directory 아래 pg_wal directory 에 segment file 로 저장되며, 16mb
-
--wal-segsize init db option을 변경하여 수정 가능
-
segement page는 8kb (--with-wal-blocksize option)
-
WAL record header 는 access/xlogrecord.h 에 설명 (https://github.com/postgres/postgres/blob/master/src/include/access/xlogrecord.h)
-
- WAL 파일 은 별도의 Disk 공간으로 분리 하는 것이 유리
- pg_wal directory를 symbolic link 로 처리하면 가능
- Checkpoint 가 발생 시, WAL 내용도 flush 된 후, checkpoint 의 값은 pg_control 에 저장
-
DB Crash 이후 recovery 진행할 때, 가장 먼저 pg_control 값을 확인 후, 이후 부터 wal 파일 조회하여 복구 진행
-
pg_control 이 손상되면, 최신 checkpoint 를 찾기 위해 WAL segment 를 역순으로 체크하면 되는데, 이것은 아직 구현되지 않음
-
또한, pg_control 이 손상되어 DB를 복구 하지 못한 것은 아직 보고가 되지 않음
-
-
- 참고로 checkpoint 는 checkpoint 이전까지의 기록된 transaction 의 sequence 지점
그 외 좋은 Tip 소개
[Why PostgreSQL WAL Archival is Slow]
-
Disk 사용량이 급증하는 경우, WAL (pg_wal) Directory 의 size 가 높은 경우가 종종 발생
-
왜 rotation 안되고, 증가하는 것인지에 대한 의문
-
WAL Archival 의 실패
-
오래된 WAL의 slot 을 holding 하는 경우
-
최근에는, WAL segment 생성 속도에 비해, 삭제 속도가 느려서 발생하는 현상도 추가
-
Host (Instance) 서버의 처리 능력 증가
- 파티셔닝 기능의 발전이나 대량 데이터 로딩 이 개선되면서 Postgresql 의 확장성 향상
- 빠른 차세대 Storage 로 인해 처리량 증가이로 인해 WAL 가 생성되는 속도가 증가
-
- 이로 인해 WAL 가 생성되는 속도가 증가
-
WAL-G 또는 pgBackRest 와 같은 백업 솔루션이 내장된 압축 기능으로 문제 해결도 가능
'PostgreSQL > PostgreSQL-Study' 카테고리의 다른 글
[pgday.Seoul 2022] PostgreSQL구조 - 윤성재 님 요약 (0) | 2024.06.30 |
---|---|
[Postgresql] 에 대한 소개 - 1st study (1) | 2024.06.27 |
Postgresql - Study 준비 (0) | 2024.06.10 |