본문 바로가기
🗄️ DB_이야기/# 🐘 PostgreSQL

🐘[PostgreSQL] 수동 장애 전환(Fail-Over)과 복구(Fail-Back)

by gwon_s 2025. 7. 24.

🔍 들어가며

이번 글에서는 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)