🔍 들어가며
이번 글에서는 PostgreSQL 환경에서 수동 장애 전환(Fail-Over)과 복구(Fail-Back) 개념에 대해 정리해보려 합니다.
운영 환경에서 고가용성(HA)을 확보하기 위해 중요한 기능인 만큼
개념 → 절차 → 실무 포인트 중심으로 정리해보겠습니다.
🚨 수동 장애 전환(Fail-Over)이란?
Primary(DB Master) 노드에 문제가 생겼을 때, Standby(DB Slave) 노드를 수동으로 승격(Promote)하여 서비스 연속성을 유지하는 작업
- 자동 장애 전환은 Patroni, repmgr, pg_auto_failover 등으로 가능하지만
- 운영 안정성과 예측성을 중요하게 생각하는 환경에서는 수동 방식이 선호되기도 합니다.
🔁 복구(Fail-Back)란?
장애가 해결된 Primary를 다시 원래의 역할로 복귀시키는 작업
- 즉, 현재 운영 중인 Standby 노드를 다시 Standby로 내리고 이전 Primary를 다시 Primary로 올리는 과정입니다.
🛠️ 실습 기반 수동 Fail-Over & Fail-Back 절차
서버 환경
| 데이터베이스 | 운영체제(OS) | Public IP | Private IP | Hostname | |
| Primary Server | PostgreSQL 17 | Oracle Linux 9 (OCI) | 134.185.102.159 | 10.0.0.61 | postdb1 |
| Standby Server | PostgreSQL 17 | Oracle Linux 9 (OCI) | 146.56.115.180 | 10.0.0.117 | postdb2 |
1️⃣ Primary 장애 발생 확인
1. primary 서버 네트워크가 살아 있는지 확인(Standby)
$ ping 10.0.0.61
2. primary 서버의 PostgrSQL 포트가 열려있는지 확인(Standby)
$ telnet 10.0.0.61 5432
3. DB 접속 테스트(Standby)
$ psql -h 10.0.0.61 -u postgres
4. 프로세스 확인(Primary)
ps -ef | grep postgres
2️⃣ 수동 Fail-Over (Standby → Primary 승격)
1. Standby DB의 postgresql.conf 파일 수정(Standby)
- %p → 아카이브할 WAL 파일의 경로
-- archive 관련 파라미터 주석 해제
-- Standby DB가 Primary DB로 전환 되면 아카이브 로그를 남겨야하기 때문
[postgres@gwon-sub ~]$ vi /postgres/app/postgres/pgsql17/data/postgresql.conf
...(생략)...
archive_mode = on
archive_command = 'cp %p /postgres/app/postgres/pgsql17/pg_arch/%f'
archive_timeout = 120
...(생략)...
2. Standby DB를 Primary DB로 전환(Standby)
- promte → standby(복제본) 서버를 primary(주) 서버로 승격시킵니다.
[postgres@gwon-sub ~]$ $PG_HOME/bin/pg_ctl promote
3. Standby DB를 Primary DB로 전환 후 정상작동 하는지 확인
- 기존 테이블에 임시 데이터 insert
postgres=# insert into repl_config values(5, 'test5', now());
4. 장애 난 기존 Primary 서버의 HA 재구성 후 DB 기동(Primary)
- 스탠바이(Standby) 서버임을 지정하기 위해 사용하는 신호 파일(standby.signal)을 생성
- standby.signal은 단순한 빈 파일입니다. 파일이 존재하기만 하면 됩니다.
- pg_ctl promote 명령을 사용하면 PostgreSQL은 이 파일을 삭제하고 스스로 primary 역할을 시작합니다.
- 기존 Standby 서버의 postgresql.auto.conf파일 내용 복사 후 붙여넣기, host IP는 그대로 기존 Standby IP로 작성
[postgres@gwon-main data]$ touch $PG_HOME/data/standby.signal
[postgres@gwon-main data]$ chmod 600 standby.signal
[postgres@gwon-main data]$ vi postgresql.auto.conf
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
primary_conninfo = 'user=repl_user passfile=''/home/postgres/.pgpass'' channel_binding=disable host=10.0.0.117 port=5432 sslmode=disable sslnegotiation=postgres sslcompression=0 sslcertmode=disable sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres gssdelegation=0 target_session_attrs=any load_balance_hosts=disable'
5. 기존 Primary 서버의 DB 기동(Primary)
[postgres@gwon-main ~]$ $PG_HOME/bin/pg_ctl -D $PGDATA start
💡 위와 같은 순서대로 작업을 수행하면 수동 장애 전환(Fail-Over)이 완료되어, 기존 Standby 서버는 Primary로 전환되어 Read/Write가 가능해지고, 기존 Primary 서버는 Standby로 전환되어 Read-Only 상태로 동작하게 됩니다.
이후 다시 1번 서버가 Primary로 동작하도록 하려면, 아래 절차에 따라 복구(Fail-Back)를 진행하면 됩니다.
3️⃣ 수동 Fail-Back (복구된 서버를 다시 Primary로)
1. 기존 Primary 복구 및 재설정(Primary)
- 백업을 위한 DB 종료
[postgres@gwon-main pgsql17]$ $PG_HOME/bin/pg_ctl -D $PGDATA stop
- 백업될 data폴더 설정
-- 백업을 위해 기존 Primary(10.0.0.61) 서버의 data폴더를 임시 폴더로 변경하기
[postgres@gwon-main ~]$ mv $PG_HOME/data $PG_HOME/data_temp
-- 다시 data 폴더 생성
[postgres@gwon-main ~]$ mkdir $PG_HOME/data
- 백업 진행
-- 기존 Standby(10.0.0.117) DB에서 Primary(10.0.0.61)로 백업해오기
[postgres@gwon-main pgsql17]$ pg_basebackup -h 10.0.0.117 -D $PGDATA -U repl_user -P -R
-- 백업된 data폴더 권한 설정
[postgres@gwon-main pgsql17]$ chmod 700 data
- 파일 설정
--host 부분의 ip를 primary가 될 ip로 변경
[postgres@gwon-main data]$ vi postgresql.auto.conf
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
primary_conninfo = 'user=repl_user passfile=''/home/postgres/.pgpass'' channel_binding=disable host=10.0.0.61 port=5432 sslmode=disable sslnegotiation=postgres sslcompression=0 sslcertmode=disable sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres gssdelegation=0 target_session_attrs=any load_balance_hosts=disable'
[postgres@gwon-main data]$ vi postgresql.conf
...(생략)...
hot_standby = off
archive_mode = on
archive_command = 'cp %p /postgres/app/postgres/pgsql17/pg_arch/%f'
archive_timeout = 120
...(생략)...
- DB 기동
[postgres@gwon-main pgsql17]$ $PG_HOME/bin/pg_ctl -D $PGDATA start
2. 기존 Standby DB 종료(Standby)
(Standby)
[postgres@gwon-sub data]$ $PG_HOME/bin/pg_ctl -D $PGDATA stop
3. postgresql.conf 파일 수정(Standby)
- postgresql.conf 파일에서 아카이브 관련 파라미터 주석처리
[postgres@gwon-sub ~]$ vi $PGDATA/postgresql.conf
...(생략)...
#archive_mode = on
#archive_command = 'cp %p /postgres/app/postgres/pgsql17/pg_arch/%f'
#archive_timeout = 120
...(생략)...
4. 기존 Primary를 👉 다시 Primary로 전환(Primary)
[postgres@gwon-main pgsql17]$ $PG_HOME/bin/pg_ctl -D $PGDATA promote
5. Standby 서버의 HA 재구성 후 DB 기동(Standby)
- standby.signal 파일 생성
[postgres@gwon-sub ~]$ cd $PGDATA
[postgres@gwon-sub data]$ touch standby.signal
[postgres@gwon-sub data]$ chmod 600 standby.signal
- postgresql.auto.conf 파일 수정
- host의 ip를 primary ip로 변경
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
primary_conninfo = 'user=repl_user passfile=''/home/postgres/.pgpass'' channel_binding=disable host=10.0.0.61 port=5432 sslmode=disable sslnegotiation=postgres sslcompression=0 sslcertmode=disable sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres gssdelegation=0 target_session_attrs=any load_balance_hosts=disable'
6. Standby DB 기동(Standby)
[postgres@gwon-sub ~]$ $PG_HOME/bin/pg_ctl -D $PGDATA start
4️⃣ Primary - Standby 데이터 동기화 테스트
1. replocation 상태 확인(Primary)
postgres=# select * from repl_config;
id | product_name | created_time
----+--------------+----------------------------
1 | test1 | 2025-07-16 23:49:58.948302
2 | test2 | 2025-07-16 23:50:04.131882
3 | test3 | 2025-07-16 23:50:08.265657
4 | test4 | 2025-07-16 23:50:12.332795
5 | test5 | 2025-07-22 04:09:34.050294
6 | test6 | 2025-07-22 06:04:29.629289
(6 rows)'🗄️ DB_이야기 > # 🐘 PostgreSQL' 카테고리의 다른 글
| 🐘 [PostgreSQL] 기동 실패 에러: "could not bind IPv4 address" (3) | 2025.07.24 |
|---|---|
| 🐘 [PostgreSQL] 타임라인 에러: "requested timeline is not a child of this server's history" (3) | 2025.07.24 |
| 🐘 [PostgreSQL] PostgreSQL 17 고가용성(HA) 이중화 설치 가이드(2) (4) | 2025.07.17 |
| 🐘 [PostgreSQL] PostgreSQL 17 고가용성(HA) 이중화 설치 가이드(1) (0) | 2025.07.16 |
| 🐘 [PostgreSQL] Vacuum (1) | 2025.07.11 |