Replication Slot 탄생
PostgreSQL에서 안정적인 Replication 유지를 위한 WAL 파일의 관리는 항상 어려운 문제였습니다. Standby Server의 연결이 끊어진 상태에서 Main Server의 WAL 파일이 재사용(Overwrite) 되면 Replication 상태를 유지할 수 없으므로 다음과 같은 에러를 마주하게 됩니다.
LOG: started streaming WAL from primary at 0/3000000 on timeline 1
FATAL: could not receive data from WAL stream:
ERROR: requested WAL segment 000000010000000000000003 has already been removed
그리고 이러한 상황이 발생하기까지 적절한 조치를 취하지 못했다면, Replication을 지속하기 위해 Standby Server를 다시 구성해야 합니다. 물론, 이를 피하기 위해 운영자는 max_wal_size
(PostgreSQL 9.5 버전 까지는 max_keep_segments
) 파라미터를 조정하는 등, WAL 파일 보관 정책을 세워 관리했을 것입니다.
PostgreSQL 9.4 버전부터 도입된 Replication Slot은 Standby Server와의 연결이 끊어져도 필요한 WAL 파일이 Main Server에 유지되도록 하는 기능을 말합니다. Replication Slot을 통해 WAL 파일(또는 Record)이 Standby Server에 전달되면, WAL 파일을 삭제/재사용합니다.
Replication Slot 사용 장점
- Slot을 사용한 Replication의 경우 Standby Server의 연결이 끊어진 경우에도 다시 연결이 될 때 필요한 WAL 파일을 유지할 수 있습니다.
- Standby Server가 필요한 WAL 파일에 대한 보관을 자동으로 관리하기 때문에 운영자가 WAL 파일 보관 설정에 대한 고민을 할 필요가 없습니다.
Replication Slot 사용 단점
- Standby Server가 연결이 끊긴 경우 WAL 파일이 재사용되지 않고 유지되어 Main Server의 Disk Full을 발생시킬 수 있습니다.(pg_wal Directory)
- Replication Slot은 자동으로 삭제되지 않기 때문에 Replication을 유지하지 않을 경우 위와 같은 이유로 Replication Slot을 운영자가 삭제해야 합니다.
Replication Slot은 Physical Replication Slot과 Logical Replication Slot으로 구분됩니다.
Physical Replication Slot
Physical Replication Slot은 Streaming Replication에서 사용할 수 있습니다. Main Server에서 발생하는 변경 사항들은 WAL 파일에 기록됩니다. Physical Replication Slot은 WAL 파일에 기록된 내용을 읽어 Standby Server와 동기화를 유지할 수 있습니다.
Physical Replication Slot 생성
-- pg_create_physical_replication_slot Syntax
SELECT pg_create_physical_replication_slot( slot_name [, immediately_reserve , temporary ] ) ;
-- example
SELECT pg_create_physical_replication_slot( slot_name , immediately_reserve true , temporary true ) ;
SELECT pg_create_physical_replication_slot( 'pslot' ) ;
pg_create_physical_replication_slot
-------------------------------------
(pslot,)
Physical Replication Slot 확인
[postgres@main ~] ls -l /var/lib/pgsql/14/data/pg_replslot
drwx------ 2 postgres postgres 19 Feb 24 14:34 pslot
SELECT *
FROM pg_replication_slots
WHERE slot_type = 'physical' ;
-[ RECORD 1 ]-------+---------
slot_name | pslot
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | t
active_pid | 36491
xmin |
catalog_xmin |
restart_lsn | 0/A000060
confirmed_flush_lsn |
wal_status | reserved
safe_wal_size |
two_phase |
pg_replication_slots Catalog를 통해서 Replication Slot에 대한 정보를 확인할 수 있습니다. 위 예시에서 pslot은 restart_lsn
컬럼을 통해 0/A000060 이전의 WAL 파일은 제거하지 않을 것임을 확인할 수 있습니다.
Logical Replication Slot
Logical Replication Slot은 Physical Replication Slot과 달리 논리적 디코딩이라는 메커니즘을 통해 디코딩된 메시지를 통해 복제를 합니다. 논리적인 변경 사항을 기반으로 복제를 수행하므로 Physical Replication Slot보다 유연한 데이터 복제(특정 스키마, 테이블 등)가 가능합니다.
Logical Replication Slot 생성
-- pg_create_logical_replication_slot Syntax
SELECT pg_create_logical_replication_slot( slot_name , plugin [, temporary , two_phase ] ) ;
-- example
SELECT pg_create_logical_replication_slot( slot_name , pgoutput , temporary true , two_phase true ) ;
SELECT pg_create_logical_replication_slot( 'lslot' , 'pgoutput' ) ;
pg_create_logical_replication_slot
------------------------------------
(lslot,0/A000650)
Logical Replication Slot은 Physical Replication Slot과 달리 pgoutput
모듈을 사용하여 복제를 수행합니다. pgoutput
모듈은 PostgreSQL 10 버전부터 기본으로 제공되며, 변경 사항을 출력하는 데 사용됩니다. Logical Replication Slot 생성 시 현재 트랜잭션의 로그 위치가 반환되며(0/A000650), 이 위치부터 논리적으로 디코딩된 WAL Record가 Standby Server로 전송됩니다.
Logical Replication Slot 확인
SELECT *
FROM pg_replication_slots
WHERE slot_type = 'logical' ;
-[ RECORD 1 ]-------+----------------
slot_name | lslot
plugin | pgoutput
slot_type | logical
datoid | 14486
database | postgres
temporary | f
active | t
active_pid |
xmin |
catalog_xmin | 791
restart_lsn | 4/55BC9E68
confirmed_flush_lsn | 4/55BC9EA0
wal_status | reserved
safe_wal_size |
two_phase | f
Logical Replication Slot Plugin 종류
종류 | 설명 |
pgoutput | Logical Replication에서 사용되는 표준 출력 Plugin Database의 변경 사항을 이전형식(Binary)으로 제공 |
test_decoding | Database의 변경 사항을 사람이 읽을 수 있는 형식으로 제공하여, 주로 테스트 및 개발목적으로 사용 |
wal2json | Database의 변경 사항을 JSON 형식으로 제공(3rd-party Plugin) |
Replication Slot의 위험성
Replication Slot은 서버 장애 상황에서도 Replication이 유지되기 위해 설계되었지만, Slot을 사용하는 응용프로그램의 상태는 알 수 없습니다. 따라서, 생성된 Slot이 사용되지 않는 경우도 있을 수 있습니다. 이러한 경우, 아직 반영되지 않은 WAL 파일을 계속 보관해야 하기 때문에 VACUUM에 의해서 정리되지 않습니다. 이러한 상태가 계속 유지될 경우 극단적으로 XID Wraparound를 방지하기 위해 PostgreSQL가 종료될 수 있으므로, 더 이상 필요하지 않은 Slot은 삭제해야 합니다.
Replication Slot 유무에 따른 pg_wal 사이즈 변화
테스트 테이블을 생성하고 WAL 파일들의 합이 1GB가 되도록 데이터를 입력합니다. 본 테스트에서는 약 17만건 데이터 입력 시 하나의 WAL파일(16MB)이 생성되며, 총 64개의 WAL 파일이 생성되도록 데이터를 입력합니다. (16MB * 64 = 1024MB)
-- 테이블생성
CREATE TABLE test01 ( c1 integer , c2 text ) ;
-- WAL 파일이 1GB 데이터 입력
INSERT INTO test01
SELECT generate_series( 1 , 170000 ) , md5( random()::text )
FROM generate_series( 1 , 64 ) ;
실제로 pg_wal 디렉토리에 64개의 WAL 파일이 생성되었고 그 크기가 1009 MB인 것을 알 수 있습니다.
## pg_wal 디렉토리 확인
[postgres@main ~] ls /var/lib/pgsql/14/data/pg_wal
000000010000000000000023 000000010000000000000030 00000001000000000000003D 00000001000000000000004A 000000010000000000000057
000000010000000000000024 000000010000000000000031 00000001000000000000003E 00000001000000000000004B 000000010000000000000058
000000010000000000000025 000000010000000000000032 00000001000000000000003F 00000001000000000000004C 000000010000000000000059
000000010000000000000026 000000010000000000000033 000000010000000000000040 00000001000000000000004D 00000001000000000000005A
000000010000000000000027 000000010000000000000034 000000010000000000000041 00000001000000000000004E 00000001000000000000005B
000000010000000000000028 000000010000000000000035 000000010000000000000042 00000001000000000000004F 00000001000000000000005C
000000010000000000000029 000000010000000000000036 000000010000000000000043 000000010000000000000050 00000001000000000000005D
00000001000000000000002A 000000010000000000000037 000000010000000000000044 000000010000000000000051 00000001000000000000005E
00000001000000000000002B 000000010000000000000038 000000010000000000000045 000000010000000000000052 00000001000000000000005F
00000001000000000000002C 000000010000000000000039 000000010000000000000046 000000010000000000000053 000000010000000000000060
00000001000000000000002D 00000001000000000000003A 000000010000000000000047 000000010000000000000054 000000010000000000000061
00000001000000000000002E 00000001000000000000003B 000000010000000000000048 000000010000000000000055 000000010000000000000062
00000001000000000000002F 00000001000000000000003C 000000010000000000000049 000000010000000000000056 archive_status
## pg_wal 디렉토리 사이즈 확인
[postgres@main ~] du -sh /var/lib/pgsql/14/data/pg_wal
1009M /var/lib/pgsql/14/data/pg_wal
Main Server에서 생성된 WAL 파일의 내용을 Standby Server에서 전부 수신했다면, Main Server의 pg_wal 디렉토리는 max_wal_size
에 설정된 1GB 안에서 WAL 파일이 재사용됩니다.
📢 max_wal_size
Parameter의 기본값은 1GB입니다.
## pg_wal 디렉토리 확인
[postgres@main ~] ls /var/lib/pgsql/14/data/pg_wal
000000010000000000000086 000000010000000000000093 0000000100000000000000A0 0000000100000000000000AD 0000000100000000000000BA
000000010000000000000087 000000010000000000000094 0000000100000000000000A1 0000000100000000000000AE 0000000100000000000000BB
000000010000000000000088 000000010000000000000095 0000000100000000000000A2 0000000100000000000000AF 0000000100000000000000BC
000000010000000000000089 000000010000000000000096 0000000100000000000000A3 0000000100000000000000B0 0000000100000000000000BD
00000001000000000000008A 000000010000000000000097 0000000100000000000000A4 0000000100000000000000B1 0000000100000000000000BE
00000001000000000000008B 000000010000000000000098 0000000100000000000000A5 0000000100000000000000B2 0000000100000000000000BF
00000001000000000000008C 000000010000000000000099 0000000100000000000000A6 0000000100000000000000B3 0000000100000000000000C0
00000001000000000000008D 00000001000000000000009A 0000000100000000000000A7 0000000100000000000000B4 0000000100000000000000C1
00000001000000000000008E 00000001000000000000009B 0000000100000000000000A8 0000000100000000000000B5 0000000100000000000000C2
00000001000000000000008F 00000001000000000000009C 0000000100000000000000A9 0000000100000000000000B6 0000000100000000000000C3
000000010000000000000090 00000001000000000000009D 0000000100000000000000AA 0000000100000000000000B7 0000000100000000000000C4
000000010000000000000091 00000001000000000000009E 0000000100000000000000AB 0000000100000000000000B8 0000000100000000000000C5
000000010000000000000092 00000001000000000000009F 0000000100000000000000AC 0000000100000000000000B9 archive_status
Standby Server 종료
Standby Server가 종료된 상태에서 Main Server에 대량의 트랜잭션이 발생했다고 가정해 보겠습니다. 이때 Replication Slot의 존재 유무에 따라 pg_wal 디렉토리의 크기는 전혀 다른 모습을 보입니다.
Replication Slot을 사용하지 않을 경우 Main Server는 Standby Server의 WAL 파일 수신 여부를 고려하지 않으므로, max_wal_size
로 설정된 크기를 유지하기 위해 기존의 WAL 파일을 재사용(Overwrite)합니다.
## Replication Slot을 사용하지 않는 Replication 구성
## pg_wal 디렉토리 확인
[postgres@main ~] ls /var/lib/pgsql/14/data/pg_wal
0000000100000000000000C8 0000000100000000000000D5 0000000100000000000000E2 0000000100000000000000EF 0000000100000000000000FC
0000000100000000000000C9 0000000100000000000000D6 0000000100000000000000E3 0000000100000000000000F0 0000000100000000000000FD
0000000100000000000000CA 0000000100000000000000D7 0000000100000000000000E4 0000000100000000000000F1 0000000100000000000000FE
0000000100000000000000CB 0000000100000000000000D8 0000000100000000000000E5 0000000100000000000000F2 0000000100000000000000FF
0000000100000000000000CC 0000000100000000000000D9 0000000100000000000000E6 0000000100000000000000F3 000000010000000100000000
0000000100000000000000CD 0000000100000000000000DA 0000000100000000000000E7 0000000100000000000000F4 000000010000000100000001
0000000100000000000000CE 0000000100000000000000DB 0000000100000000000000E8 0000000100000000000000F5 000000010000000100000002
0000000100000000000000CF 0000000100000000000000DC 0000000100000000000000E9 0000000100000000000000F6 000000010000000100000003
0000000100000000000000D0 0000000100000000000000DD 0000000100000000000000EA 0000000100000000000000F7 000000010000000100000004
0000000100000000000000D1 0000000100000000000000DE 0000000100000000000000EB 0000000100000000000000F8 000000010000000100000005
0000000100000000000000D2 0000000100000000000000DF 0000000100000000000000EC 0000000100000000000000F9 000000010000000100000006
0000000100000000000000D3 0000000100000000000000E0 0000000100000000000000ED 0000000100000000000000FA 000000010000000100000007
0000000100000000000000D4 0000000100000000000000E1 0000000100000000000000EE 0000000100000000000000FB archive_status
## pg_wal 디렉토리 사이즈 확인
[postgres@main ~] du -sh /var/lib/pgsql/14/data/pg_wal
1009M /var/lib/pgsql/14/data/pg_wal
반면, Replication Slot을 사용 중이라면 Standby Server의 WAL 파일 수신 여부를 체크한 후, 수신이 불가한 상태라면 max_wal_size
크기 이상으로 pg_wal 공간이 증가할 수 있습니다. 이는 Standby Server가 WAL 파일을 수신할 때까지 파일을 보관하기 때문인데, 별다른 조치가 없다면 Main Server의 Disk Full 혹은 XID Wraparound 방지를 위한 PostgreSQL 종료등의 문제가 발생할 수 있습니다.
## Replication Slot을 사용하는 Replication 구성
## pg_wal 디렉토리 확인
[postgres@main ~] ls /var/lib/pgsql/14/data/pg_wal
000000010000000000000063 000000010000000000000083 0000000100000000000000A3 0000000100000000000000C3 0000000100000000000000E3
000000010000000000000064 000000010000000000000084 0000000100000000000000A4 0000000100000000000000C4 0000000100000000000000E4
000000010000000000000065 000000010000000000000085 0000000100000000000000A5 0000000100000000000000C5 0000000100000000000000E5
000000010000000000000066 000000010000000000000086 0000000100000000000000A6 0000000100000000000000C6 0000000100000000000000E6
000000010000000000000067 000000010000000000000087 0000000100000000000000A7 0000000100000000000000C7 0000000100000000000000E7
000000010000000000000068 000000010000000000000088 0000000100000000000000A8 0000000100000000000000C8 0000000100000000000000E8
000000010000000000000069 000000010000000000000089 0000000100000000000000A9 0000000100000000000000C9 0000000100000000000000E9
00000001000000000000006A 00000001000000000000008A 0000000100000000000000AA 0000000100000000000000CA 0000000100000000000000EA
00000001000000000000006B 00000001000000000000008B 0000000100000000000000AB 0000000100000000000000CB 0000000100000000000000EB
00000001000000000000006C 00000001000000000000008C 0000000100000000000000AC 0000000100000000000000CC 0000000100000000000000EC
00000001000000000000006D 00000001000000000000008D 0000000100000000000000AD 0000000100000000000000CD 0000000100000000000000ED
00000001000000000000006E 00000001000000000000008E 0000000100000000000000AE 0000000100000000000000CE 0000000100000000000000EE
00000001000000000000006F 00000001000000000000008F 0000000100000000000000AF 0000000100000000000000CF 0000000100000000000000EF
000000010000000000000070 000000010000000000000090 0000000100000000000000B0 0000000100000000000000D0 0000000100000000000000F0
000000010000000000000071 000000010000000000000091 0000000100000000000000B1 0000000100000000000000D1 0000000100000000000000F1
000000010000000000000072 000000010000000000000092 0000000100000000000000B2 0000000100000000000000D2 0000000100000000000000F2
000000010000000000000073 000000010000000000000093 0000000100000000000000B3 0000000100000000000000D3 0000000100000000000000F3
000000010000000000000074 000000010000000000000094 0000000100000000000000B4 0000000100000000000000D4 0000000100000000000000F4
000000010000000000000075 000000010000000000000095 0000000100000000000000B5 0000000100000000000000D5 0000000100000000000000F5
000000010000000000000076 000000010000000000000096 0000000100000000000000B6 0000000100000000000000D6 0000000100000000000000F6
000000010000000000000077 000000010000000000000097 0000000100000000000000B7 0000000100000000000000D7 0000000100000000000000F7
000000010000000000000078 000000010000000000000098 0000000100000000000000B8 0000000100000000000000D8 0000000100000000000000F8
000000010000000000000079 000000010000000000000099 0000000100000000000000B9 0000000100000000000000D9 0000000100000000000000F9
00000001000000000000007A 00000001000000000000009A 0000000100000000000000BA 0000000100000000000000DA 0000000100000000000000FA
00000001000000000000007B 00000001000000000000009B 0000000100000000000000BB 0000000100000000000000DB 0000000100000000000000FB
00000001000000000000007C 00000001000000000000009C 0000000100000000000000BC 0000000100000000000000DC 0000000100000000000000FC
00000001000000000000007D 00000001000000000000009D 0000000100000000000000BD 0000000100000000000000DD 0000000100000000000000FD
00000001000000000000007E 00000001000000000000009E 0000000100000000000000BE 0000000100000000000000DE 0000000100000000000000FE
00000001000000000000007F 00000001000000000000009F 0000000100000000000000BF 0000000100000000000000DF archive_status
000000010000000000000080 0000000100000000000000A0 0000000100000000000000C0 0000000100000000000000E0
000000010000000000000081 0000000100000000000000A1 0000000100000000000000C1 0000000100000000000000E1
000000010000000000000082 0000000100000000000000A2 0000000100000000000000C2 0000000100000000000000E2
## pg_wal 디렉토리 사이즈 확인
[postgres@main ~] du -sh /var/lib/pgsql/14/data/pg_wal
2.5G /var/lib/pgsql/14/data/pg_wal
Replication Slot Parameter
PostgreSQL Replication Slot을 사용하기 위해서는 max_replication_slots
과 wal_level
Parameter를 확인해야 합니다.
max_replication_slots
Parameter는 PostgreSQL이 사용할 수 있는 Replication Slot의 개수를 지정할 수 있으며, 최소 Standby Server 개수만큼 지정해야 합니다.- Main Server의 내용을 복제하는데 pg_basebackup 등을 사용할 경우 Standby Server 수 + 1로 설정해야 합니다.
wal_level
Parameter는 WAL 파일에 기록되는 양을 제어하는 파라미터로 기본값replica
이며 Physical Replication Slot을 사용합니다.logical
로 사용하는 경우 Logical Replication Slot을 사용합니다.
📢 max_replication_slots
은 PostgreSQL 10 버전부터 기본값이 10입니다. PostgreSQL 9.6 버전까지는 기본값이 0입니다.
max_replication_slots < 1로 설정되어 있을 경우 Replication Slot은 생성되지 않습니다.
SHOW max_replication_slots;
max_replication_slots
-----------------------
0
SELECT pg_create_physical_replication_slot( 'physical_slot' ) ;
ERROR: replication slots can only be used if max_replication_slots > 0
기획 및 글 | DB기술기획팀
이미지 제작 | 브랜드디자인팀
'엑셈 경쟁력 > DB 인사이드' 카테고리의 다른 글
DB 인사이드 | PostgreSQL Extension - PG_STAT_MONITOR (0) | 2023.09.21 |
---|---|
DB 인사이드 | PostgreSQL HOT - 3. Fillfactor와 HOT Update (1) | 2023.08.31 |
DB 인사이드 | PostgreSQL Replication - Parameter (6) | 2023.07.26 |
DB 인사이드 | PostgreSQL Replication - 설정 확인 (0) | 2023.06.29 |
DB 인사이드 | PostgreSQL Replication - Catalog (0) | 2023.06.29 |
댓글