PostgreSQL 의 복제구성으로 가장 널리 쓰이는 방법은
streaming replication + physical replication slot 입니다.
특히 physical replication slot 을 사용하는 경우에는 DB에서 slave 가 필요로 하는 WAL logfile 정보를 관리하기 때문에
운영자가 wal_keep_segments , max_wal_size 같은 WAL 보관 설정에 대해 고민할 필요가 없습니다.

그러나 이 편리한 replication slot 기능에도 예외상황이 있는데요
slave DB가 계속 replication 을 받지 못하는 상황이거나,
사용하지 않는 replication slot이 방치 된 경우
DB는 WAL logfile들이 나중엔 반영될 거라고 보기 때문에 계속~ 무한정 ~ file들을 저장하게 됩니다. 때문에 서버 디스크 이슈가 발생할 수 있습니다.

WAL 보관 설정 확인

postgres=# select name,setting from pg_settings where name in ('max_wal_size','min_wal_size','wal_keep_segments','wal_segment_size');
       name        | setting
-------------------+----------
 max_wal_size      | 128
 min_wal_size      | 128
 wal_keep_segments | 0
 wal_segment_size  | 16777216
(4 rows)

replication slot 비활성 상태일 때

CREATE TABLE t(id INT, pad CHAR(200)); 
CREATE INDEX t_id ON t (id); 
INSERT INTO t SELECT generate_series(1,1000000) AS id, md5((random()*1000000)::text) AS pad;

UPDATE t SET pad = md5((random()*1000000)::text);  <== 반복 수행


$ du -sh pg_wal
129M    pg_wal

=> 대량의 WAL log를 떨구는 커맨드를 수행해도 max_wal_size 설정을 초과해서 파일이 쌓이지 않습니다.

replication slot이 활성 상태지만, 복제는 안되는 상황일때

postgres=# select * from pg_replication_slots;
-[ RECORD 1 ]-------+-------------
slot_name           | repl_slot_01
plugin              |
slot_type           | physical
datoid              |
database            |
temporary           | f
active              | f
active_pid          |
xmin                |
catalog_xmin        |
restart_lsn         | 4/F90000D0
confirmed_flush_lsn |

=> active f , active_pid NULL ,

postgres=# UPDATE t SET pad = md5((random()*1000000)::text);
UPDATE 1000000


$ du -sh pg_wal
145M    pg_wal
$ du -sh pg_wal
209M    pg_wal
.
.
$ du -sh pg_wal
2.0G    pg_wal

=> replication_slot 활성화 상태라서 slave 에 반영안된 wal logfile들을 쭉 보관하게됩니다
이때는 max_wal_size, wal_keep_segments 설정과는 상관없으며 이처럼 replication_slot 이 활성화 된 상태에서
replication 만 안되는 상황에서는 디스크 용량 이슈가 발생할 수 있습니다.

replication slot이 활성 상태, 복제도 정상인 상황일때

postgres=# SELECT redo_lsn, slot_name,restart_lsn,
round((redo_lsn-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
-[ RECORD 1 ]-------------
redo_lsn    | 5/732000B0
slot_name   | repl_slot_01
restart_lsn | 4/F90000D0
gb_behind   | 1.91

=> slave 에 반영안되어서 보관하고 있는 wal logfile 이 2GB

slave) pg_ctl -D /home1/irteam/psql/engn/PGSQL start


postgres=# SELECT redo_lsn, slot_name,restart_lsn,
round((redo_lsn-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
-[ RECORD 1 ]-------------
redo_lsn    | 5/9A1FEB88
slot_name   | repl_slot_01
restart_lsn | 5/A0C6A000
gb_behind   | -0.10

=> 기동 후 wal logfile을 반영하면서 보관 중이던 wal logfile도 정리됨

$ du -sh pg_wal
129M    pg_wal

정리

pg_replication_slots 기능은 DB가 필요한 wal logfile을 관리해주기 때문에 편리한 기능이지만
replication_slot이 구성된 slave db의 다운 상태가 길어질 수록 예기치 못한 디스크 용량 이슈가 발생할 수 있어 주의가 필요합니다.