26.5. 상시 대기

26.5.1. 사용자 측면 개요
26.5.2. 쿼리 충돌 처리하기
26.5.3. 관리자 측면 개요
26.5.4. 상시 대기 관련 환경 설정 매개 변수 설명
26.5.5. 주의사항

여기서 말하는 상시 대기 Hot Standby란 그 서버가 아카이브 파일로 복구 작업을 하고 있거나 대기 모드로 있을 때도 클라이언트가 그 서버로 접속할 수 있으며, 읽기 전용 쿼리를 실행할 수 있는 것을 말한다. 이 기능은 복제 기능을 구현하는 방법으로, 가장 최근 상태로 백업을 하는 방법으로 유용하다. 또한 상시 대기라는 용어는 그 대기 서버로 클라이언트들이 접속해 있는 상태에서 즉시, 운영 서버로 변경해서 운영 서버에서 사용하던 쿼리를 사용할 수 있는 기능을 뜻한다.

상시 대기 모드에서 사용하는 쿼리도 크게 다르지는 않지만, 아래와 같이 몇가지 제약 사항이 있으며, 관리적인 측면에서 주의해야할 부분이 있다.

26.5.1. 사용자 측면 개요

대기 서버에서 hot_standby 매개 변수의 값이 true로 설정되면, 복구 작업으로 시스템이 일관성 있는 상태가 되었을 때 연결을 허용하게 된다. 모든 연결은 무조건 읽기 전용이다. 임시 테이블도 쓰기를 허용하지 않는다.

운영 서버에 있는 데이터는 대기 서버로 올 때까지 시간이 걸리므로 운영서버와 대기 서버 간 지연이 생긴다. 따라서 운영 서버와 대기 서버에 거의 동시에 같은 쿼리를 수행하는 것은 다른 결과를 가져올 수 있다. We say that data on the standby is eventually consistent with the primary. 트랜잭션에 커밋된 레코드가 대기 서버에서 리플레이되면, 트랜잭션 변경 사항이 스냅샷에 보인다. 스냅샷은 각 쿼리 혹은 트랜잭션이 시작될 때 찍히는데, 현재 트랜잭션의 고립 수준에 따라 다르다(자세한 정보는 13.2절을 참조).

hot standby에서 시작된 트랜잭션은 아래 명령어들을 수행할 수 있다.

  • 쿼리 접근: SELECT, COPY TO

  • 커서 명령어: DECLARE, FETCH, CLOSE

  • 설정: SHOW, SET, RESET

  • 트랜잭션 관리 명령어:

    • BEGIN, END, ABORT, START TRANSACTION

    • SAVEPOINT, RELEASE, ROLLBACK TO SAVEPOINT

    • EXCEPTION 블록과 그 외 내부적인 하위트랜잭션들

  • LOCK TABLE( ACCESS SHARE, ROW SHARE, ROW EXCLUSIVE 중 한 모드에 있을 때)

  • 계획과 리소스: PREPARE, EXECUTE, DEALLOCATE, DISCARD

  • 플러그인과 확장 모듈: LOAD

  • UNLISTEN

hot standby에서 시작된 트랜잭션은 트랜잭션 ID를 할당 받지 못하고 시스템 WAL에 쓰기 작업을 할 수 없다. 아래를 수행하면 에러 메시지를 남길 것이다.

  • 데이터 조작어 (DML): INSERT, UPDATE, DELETE, COPY FROM, TRUNCATE. 복구하는 동안 트리거를 실행할 수는 없다. 임시 테이블도 마찬가지인데, 테이블 로우는 트랜잭션 ID 없이 읽거나 쓸 수 없기 때문이다. 이 기능은 아직 Hot Standby 환경에 구현되지 않았다.

  • 데이터 정의 언어 (DDL): CREATE, DROP, ALTER, COMMENT. 이 규칙은 임시 테이블에도 적용되는데, 이 작업들을 수행하려면 시스템 카탈로그 테이블도 수정해야 하기 때문이다.

  • SELECT ... FOR SHARE | UPDATE, 로우 잠금을 하기 위해서 데이터 파일을 수정해야 할 때도 있기 때문이다.

  • DML 명령어를 생성하는 SELECT 문에 대한 규칙

  • ROW EXCLUSIVE MODE보다 높은 모드를 명시적으로 요청하는 LOCK.

  • ACCESS EXCLUSIVE MODE를 요청하는 축약된 디폴트 형태의 LOCK.

  • 읽기 전용이 아닌 상태를 명시적으로 설정한 트랜잭션 관리 명령어

    • BEGIN READ WRITE, START TRANSACTION READ WRITE

    • SET TRANSACTION READ WRITE, SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE

    • SET transaction_read_only = off

  • 두 단계의 커밋 명령어: PREPARE TRANSACTION, COMMIT PREPARED, ROLLBACK PREPARED 읽기전용의 트랜잭션도 준비 단계에서 WAL에 쓰기 작업을 해야 하기 때문이다(두 단계중 첫 번째 커밋 단계).

  • 시퀀스 업데이트: nextval(), setval()

  • LISTEN, NOTIFY

보통은 읽기 전용 트랜잭션이 LISTEN, NOTIFY를 사용하기 때문에 Hot Standby 세션들이 정상적인 읽기 전용 세션보다 조금 더 엄격하게 작업해야 한다. 추후 버전에선 이런 점이 완화될 수도 있다.

hot standby 시점에 transaction_read_only 매개 변수는 항상 true로 지속될 수 있다. 데이터베이스를 수정하려는 시도가 없는 한 hot standby 연결은 다른 데이터베이스 연결과 별반 다르지 않을 것이다. 장애처리failover나 스위치오버switchover가 발생하면 데이터베이스는 정상적인 프로세싱 모드로 전환된다. 세션은 서버 모드가 변경 돼도 연결된 상태를 유지한다. hot standby가 종료되면 읽기-쓰기 트랜잭션이 초기화될 수 있다(hot standby에서 시작된 세션조차도).

사용자는 SHOW transaction_read_only를 실행해서 읽기 전용 여부를 판별할 수 있다. 사용자는 함수 집합(표 9.86)을 통해 대기 서버 정보에 접근할 수 있다. 함수들을 사용해서 현재 데이터베이스와 연결된 프로그램을 쓸 수 있다. 복구 절차를 모니터링하거나 데이터베이스를 특정 상태로 복원하는 복잡한 프로그램을 쓸 수 있다.

26.5.2. 쿼리 충돌 처리하기

운영 서버와 대기 서버은 대부분 느슨한 연결 상태를 유지한다. 운영 서버에서 발생하는 트랜잭션 커밋은 대기서버가 그 트랜잭션을 정상적으로 커밋 했는지와 상관 없이 정상 처리된다. 이런 특성 때문에, 이런 복제 기법에는 항상 예상치 않은 장애와 두 서버간 자료 충돌이 발생할 가능성을 내포하고 있다. 가장 대표적인 자료 충돌로는 성능 저하가 발생하는 것을 꼽을 수 있을 것이다: 예를 들어 운영 서버에서 많은 자료가 입력되고 있다면, 그로 인해 많은 트랜잭션 로그가 만들어 질 것이고, 이것을 대기서버로 전달하기 위해 운영 서버는 단일 서버를 운영 할 때와 달리 부가적인 입출력 자원을 사용할 것이다. 또한 대기 서버에서도 실행 되고 있던 쿼리들이 이 입력 처리 때문에 발생하는 비용 때문에 영향을 받을 것이다.

다음은 대기 서버에서 발생할 수 있는 자료 충돌 종류들이다. 이런 충돌을 해결 하기 위해서는 어떤 경우는 실행 되고 있는 쿼리를 중지 하는 경우도 있고, 또는 세션을 중지해야 하는 경우도 발생할 것이다. 이런 의미에서 이런 충돌은 강한 충돌이라고 한다. 사용자는 이런 충돌을 잘 이해해서 각 상황에 맞는 조치를 취해야 한다:

  • 운영 서버에서 LOCK 명령을 사용했거나, 다양한 DDL 구문에 의해서 발생하는 배타적 접근 잠금 Access Exclusive Lock 에 대해서, 대기 서버는 그것에 대한 정확한 상태를 유지하지 못한다. 즉, 운영 서버에서 해당 객체가 잠겨도 대기 서버에서는 접근이 가능하다. (이렇게 되면, 대기 서버에서 읽어서 운영 서버로 반영하는 자료들이 그 정합성을 잃을 수 있다. - 옮긴이)

  • 운영 서버에서 테이블 스페이스가 삭제 되고 있는 중에도 대기 서버는 그 테이블 스페이스에 속한 객체들을 접근할 수 있다.

  • 대기 서버에 해당 데이터베이스를 사용하는 세션이 있음에도 불구하고, 운영 서버에서 해당 데이터베이스를 삭제 할 수 있다.

  • 대기 서버에서 발생한 트랜잭션을 위해 보관 되어야 할 옛 버전 자료들이 운영 서버의 vacuum 작업으로 삭제 되어 버리는 일이 생길 수 있다.

  • 위 경우와 반대로 보이지 말아야 할 옛 버전 자료들이 보여지는 경우도 발생할 수 있다.

단독으로 운영 되는 서버라면, 이런 쿼리 충돌이 일어나지 않는다. 왜냐하면, 한 작업이 마무리 되기 전까지 그 작업과 관련된 다른 세션들의 작업들은 대기 상태가 되기 때문이다. 하지만 복제 환경에서 대기 서버는 이런 대기를 제어 할 수 없다: 운영 서버에서 발생한 트랜잭션 로그를 대기 서버가 반영 하도록 전해 받았다면, 그저 그 작업을 진행할 뿐이기 때문이다. 이 작업을 진행 할 때, 운영 서버의 다른 세션 상태를 고려할 수 없기 때문이다. 물론 가장 완벽한 방법은 대기 서버까지도 모두 해당 트랜잭션 작업이 끝날 때까지 모든 세션(운영 서버의 세션과 대기 서버의 세션 모두)의 대기 상태를 유지 하는 것이지만, 현실적으로 대기 서버와 운영 서버간의 연결을 완벽하게 보장한다는 것은 거의 불가능하기 때문에, 이런 방식은 오히려 운영 서버의 안정성을 더 떨어뜨린다. 그래서, 이런 충돌이 발생했을 때 대기 서버는 충돌을 해결 하기 위한 별도의 처리 방식을 제공하고 있어야 하며, 이에 따라 몇가지 충돌 자동 해결 기능을 제공하고 있다.

그 한 예로 운영 서버에서 DROP TABLE 명령으로 한 테이블을 삭제 한다면, 대기 서버에서 아직 삭제 되지 않은 그 테이블을 조회하는 쿼리는 운영 서버에서 전달 받은 이 트랜잭션이 감지 되면 자동으로 취소 된다. 일반적으로 단독 서버 환경이면, 조회 작업이 먼저 진행 중이고, 삭제 작업이 발생 했다면, 조회 작업이 끝날 동안 삭제 작업은 기다린다. 하지만 대기 서버가 있는 상황에서는 운영 서버가 대기 서버에서 해당 테이블을 조회하는 작업이 있는지 알 수 없음으로 일단 삭제하고, 그 로그를 대기 서버로 보낸다. 이때 대기 서버의 가장 바람직한 선택은 대기 서버에서 조회 하고 있던 쿼리를 자동으로 취소하고, 최대한 빨리 운영 서버에서 실행 했던 삭제 작업을 대기 서버에도 반영 하는 것이다. 이렇게 처리하지 않고 운영 서버처럼 조회 작업이 끝날 때까지 기다렸다가 삭제 작업을 진행한다면, 오히려 자료 동기화 (복제 작업) 의 근본 목적을 달성하는데 방해가 될 것이다.

달리 생각하면, 해당 충돌이 순식간에 끝나는 경우라면, 충돌을 피하기 위해 그냥 대기서버도 운영 서버 방식을 취하는 것이 바람직할 것이다. 하지만, 대기 서버의 조회 작업이 오래 지속된다면, 트랜잭션 로그 동기화는 그만큼 지연 될 것이고, 이에 따른 다른 객체들까지 영향을 받을 것이다. 그래서, max_standby_archive_delay, max_standby_streaming_delay 환경 설정 매개 변수로 이런 최대 지연 시간을 지정해서 이 지연 시간을 넘으면 대기 서버의 작업을 중지 하도록 설정 한다. 이렇게 함으로 최대한 대기 서버의 상태를 운영 서버와 같도록 한다. 이 두 환경 설정 매개 변수는 아카이브 로그 파일 반영에서, 스트리밍 트랜잭션 로그 전달에서 최대 지연 시간을 지정하는 것이다. (이 설정값들의 초기값은 30초다. 이 값의 최적값을 찾는 것은 데이터베이스 관리자의 몫인 것 같다. - 옮긴이)

고가용성이 주 목적인 대기 서버는 쿼리 지연으로 인해 운영 서버에 뒤쳐지지 않도록 지연 매개 변수를 비교적 짧게 정하는 것이 가장 좋다. 그러나 대기 서버가 장시간 쿼리를 수행하게 된다면 지연 값을 크게 혹은 무한으로 설정하는 것이 좋다. 장시간 수행 쿼리가 WAL 레코드 적용을 지연시키면 다른 세션들이 운영 서버의 최근 변경 사항을 보지 못할 수도 있다.

max_standby_archive_delay 혹은 max_standby_streaming_delay 로 지정된 시간을 초과하면 충돌 쿼리는 취소된다. 그러면 취소 에러만 발생하는데, DROP DATABASE를 실행할 경우 전체 충돌 세션이 종료된다. 휴지 상태인 트랜잭션의 잠금이 충돌 원인일 때 충돌 세션은 종료된다(이 방법은 향후 바뀔 수 있음).

취소된 쿼리는 바로 재시도한다(새 트랜잭션을 시작한 이후에만). Since query cancellation depends on the nature of the WAL records being replayed, a query that was canceled may well succeed if it is executed again.

지연 매개 변수는 WAL 데이터를 대기 서버가 수신한 이후 경과 시간을 뜻한다는 것을 기억해 두자. 대기 서버에 있는 쿼리에 대한 유예 기간은 지연 매개 변수를 초과할 수 없다. 이전 쿼리들이 완료되기를 기다리다가 혹은 업데이트 양이 너무 많아서 이미 뒤쳐진 상태이면 지연 매개 변수보다 훨씬 작을 수도 있다.

대기 서버 쿼리와 WAL 리플레이 충돌의 원인으로 가장 잘 알려진 것은 조기 청소early cleanup이다. 보통 PostgreSQL에서는 MVCC 규칙에 따라 데이터의 가시성을 정하기 위해, 트랜잭션이 보지 않는 이전 로우 버전들을 청소할 수 있다. 하지만 이 규칙은 마스터에서 수행하는 트랜잭션에만 해당된다. 그러므로 마스터에서 청소하면 대기서버의 트랜잭션이 보고 있는 로우 버전들이 삭제될 수도 있다.

숙련된 사용자는 로우 버전 청소와 로우 버전 동결freezing이 대기 서버 쿼리들과 충돌할 수 있다는 것을 안다. VACUUM FREEZE를 수동적으로 실행하면 로우가 업데이트되거나 삭제되지 않은 테이블에도 충돌을 일으킬 수 있다.

운영 서버에서 정기적으로 대량 업데이트 된 테이블은 대기 서버에서 장시간 수행되는 쿼리를 급하게 취소할 수 있다. 이런 경우에 max_standby_archive_delaymax_standby_streaming_delay에 한정적인 값을 설정하면 statement_timeout을 설정하는 것과 비슷한 역할을 한다.

대기 서버 쿼리를 취소하는 횟수가 많아질 때를 대비하는 방법도 있다. 첫 번째 방법은 hot_standby_feedback 매개 변수를 설정하는 것인데, 최근 삭제된 로우들에 VACUUM을 수행하는 것을 막아서 청소 충돌을 방지하는 것이다. 운영 서버에서 삭제된 로우들에 대한 청소를 지연하여 테이블이 원치 않게 커질 수가 있다. 하지만 운영 서버에서 직접 대기 서버 쿼리를 실행하고 있을 때 대기 서버에서도 수행되는 경우보다는 나을 수도 있다. 이 경우, 지연된 WAL 파일에 대기 서버 쿼리와 충돌할 엔트리가 포함됐을 수 있으므로, max_standby_archive_delay가 항상 큰 값으로 유지되어야 한다.

또 다른 방법은 운영 서버에서 vacuum_defer_cleanup_age 를 증가시켜서 삭제된 로우가 평소보다 빨리 청소되는 것을 막는 것이다. max_standby_streaming_delay를 높게 설정하지 않아도 대기 서버에서 쿼리들이 취소되기 전에 수행될 시간을 더 준다. 하지만 특정 수행 시간을 보장할 수는 없는데, 운영 서버에서 실행된 트랜잭션에 vacuum_defer_cleanup_age가 반영되기 때문이다.

쿼리 취소 횟수와 취소 원인은 대기 서버의 pg_stat_database_conflicts 시스템 뷰로 확인할 수 있다. pg_stat_database 시스템 뷰에는 요약 정보도 포함돼 있다.

26.5.3. 관리자 측면 개요

postgresql.conf에서 hot_standby 상태가 on이고(기본값), standby.signal 파일이 있으면, 서버는 Hot Standby 모드로 실행될 것이다. 그러나 Hot Standby 접속이 허용되려면 시간이 꽤 걸릴 수도 있다. 서버가 일관적으로 어떤 쿼리를 실행하기 위해 복구를 끝낼 때까지 연결을 수락하지 않기 때문이다. 이 시간 동안에 연결을 시도하는 클라이언트는 에러 메시지가 뜨면서 거부될 것이다. 서버가 연결할 준비가 되었는지 확인하기 위해서는 애플리케이션 접속을 시도하는 루프를 돌거나 서버 로그에서 아래 메시지들을 찾아 볼 수 있다.

LOG:  entering standby mode

... then some time later ...

LOG:  consistent recovery state reached
LOG:  database system is ready to accept read only connections

일관성에 대한 정보는 운영 서버에 체크 포인트당 한 번 기록된다. wal_level이 운영 서버의 replica 또는 logical로 설정돼 있지 않을 때 쓰여진 WAL을 읽으면 hot standby를 켤 수 없다. 일관적인 상태는 아래 두 조건이 충족되면 지연될 수 있다.

  • 64개 이상의 부트랜잭션을 갖는 쓰기 트랜잭션이 있을 때

  • 매우 수명이 긴 트랜잭션이 있을 때

파일 기반의 로그 전달(“warm standby”)을 수행할 때 그 다음 WAL 파일이 도착할 때까지 기다려야 할 수도 있는데, 운영 서버에서 archive_timeout에 설정해 놓은 만큼 기다릴 수 있다.

대기 서버에서 설정한 일부 매개 변수들은 운영 서버에서 변경 되면 재설정되어야 한다. Therefore, if you want to increase these values, you should do so on all standby servers first, before applying the changes to the primary server. Conversely, if you want to decrease these values, you should do so on the primary server first, before applying the changes to all standby servers. 이 매개 변수들에 대한 대기 서버의 값은 운영 서버에서의 값보다 크거나 같다. 이 매개 변수들이 높게 설정돼 있지 않으면 대기 서버에서 실행할 수 없다. 높게 설정 되면 서버가 복구를 위해 재시작한다. 매개 변수들은 다음과 같다.

  • max_connections

  • max_prepared_transactions

  • max_locks_per_transaction

  • max_wal_senders

  • max_worker_processes

관리자가 max_standby_archive_delaymax_standby_streaming_delay에 적절한 설정을 해주는 것이 중요하다. 최적의 설정 방법은 비즈니스 우선순위에 따라 다르다. 예를 들어, 서버가 주로 고 가용성 서버로서의 임무를 맡으면 지연 값을 낮추는 것이 좋다. 극단적으로 0도 가능하다. 대기 서버가 decision support 쿼리를 위해 추가된 서버일 경우, 최대 지연 값을 장시간 혹은 쿼리가 끝날 때까지인 -1로 설정할 수 있다.

운영 서버에 쓰인 “hint bits” 트랜잭션 상태는 WAL로그에 기록되지 않으므로 대기 서버의 데이터가 힌트를 재사용할 수도 있다. 그러므로 대기 서버는 모든 사용자가 읽기 권한만 있어도 디스크 쓰기를 수행할 것이다. 데이터 값 자체에는 어떤 변화도 생기지 않는다. 사용자는 대용량의 정렬 임시 파일을 만들 수 있고, relcache 정보 파일을 재생성해서 hot standby mode일 때 데이터베이스의 어떤 부분도 읽기 전용이 아닌 상태로 만들 수 있다. 트랜잭션이 지역적으로 읽기 전용이라 하더라도 dblink 모듈을 사용해서 원격 데이터 베이스에 쓰기 작업을 하고, PL함수를 사용해서 데이터베이스 외부에서 다른 작업을 할 수 있다.

아래 관리 명령어 타입들은 복구 모드일 때 사용할 수 없다.

  • Data Definition Language (DDL): e.g. CREATE INDEX

  • Privilege and Ownership: GRANT, REVOKE, REASSIGN

  • Maintenance commands: ANALYZE, VACUUM, CLUSTER, REINDEX

몇 개의 명령어들은 운영 서버의 읽기 전용인 트랜잭션에만 해당된다는 것을 알아 두자.

결론적으로 대기 서버에서 단독으로 존재하는 추가 인덱스들 혹은 통계치를 생성할 수 없다. 위의 관리 명령어들이 필요할 때는 운영 서버에서 실행해야 하고, 변경 사항이 생길 시 대기 서버에 전달 된다.

pg_cancel_backend()pg_terminate_backend()는 사용자 백엔드에서 작동하고, 복구 작업을 하는 스타트업Startup 프로세스에서는 작동하지 않는다. pg_stat_activity는 이 복구 작업 중인 세션 정보는 보여 주지 않는다. 즉, pg_prepared_xacts는 복구 중에 항상 비어 있다. prepared transaction을 분석하려면, 운영 서버에 있는 pg_prepared_xacts을 보고 명령어를 실행해서 트랜잭션을 분석해야 한다.

pg_locks는 백엔드가 사용하는 잠금을 보여준다. pg_locks also shows a virtual transaction managed by the Startup process that owns all AccessExclusiveLocks held by transactions being replayed by recovery. 스타트업 프로세스는 데이터베이스를 변경할 때 잠금을 사용하지 않으므로 AccessExclusiveLocks 외의 잠금은 pg_locks에 표시되지 않는다. 잠금이 존재한다고 추정할 수밖에 없다.

Nagios 플러그인 check_pgsql 은 간단한 정보를 확인하기 위해 작동한다. check_postgres 모니터링 스크립트는 일부 예상과 다르거나 혼동되는 수치를 보여주기도 한다. 예를 들어 vacuum은 대기 서버에서 작동하지 않으므로, 최근 vacuum 시간은 보존 되지 않는다. 운영 서버에서 실행되는 vacuum은 대기 서버에 변경 사항을 전달한다.

WAL 파일을 조절하는 명령어는 복구 중에 작동하지 않는다. 예를 들면 pg_start_backup, pg_switch_wal 등이 있다.

동적으로 적재 가능한 모듈에는 pg_stat_statements가 있다.

교착상태 감지와 같은 보조 잠금 advisory lock은 복구 중에 정상적으로 작동한다. 보조 잠금은 WAL에 기록되지 않으므로, 운영 서버나 대기 서버에 있는 보조 잠금은 WAL 리플레이와 충돌하지 않는다. 운영 서버에서 보조 잠금을 획득하고, 대기 서버에서 비슷한 보조 잠금을 만들 수 없다. 보조 잠금이 획득된 서버에서만 보조 잠금을 쓸 수 있다.

SlonyLondiste, Bucardo같은 트리거 기반의 리플리케이션 시스템은 대기 서버에서 절대 실행될 수 없다. 대기 서버에 변경 사항이 전달되지 않는 한, 운영 서버에서 잘 실행될 것이다. WAL 리플레이는 트리거 기반이 아니므로, 대기 서버에서 추가적인 데이터베이스 쓰기 작업을 요구하거나 트리거 쓰임에 의존하는 시스템에 전달될 수 없다.

새로운 OID들은 할당되지 않으나, UUID 생성자generator는 데이터베이스에 새로운 상태를 쓰지 않으면 사용 가능하다.

임시 테이블은 읽기 전용 트랜잭션 수행 중에 생성될 수 없으므로, 기존 스크립트대로 작동하지 않을 수 있다. 향후 버전에서 개선될 수 있다. 현재는 SQL 표준 준수와 기술적인 문제가 결합돼 있다.

DROP TABLESPACE는 테이블스페이스가 비어 있을 때만 쓸 수 있다. 일부 대기 서버 사용자들은 temp_tablespaces로 테이블스페이스를 자주 사용하는 경우가 있다. If there are temporary files in the tablespace, all active queries are canceled to ensure that temporary files are removed, so the tablespace can be removed and WAL replay can continue.

운영 서버에서 DROP DATABASE 혹은 ALTER DATABASE ... SET TABLESPACE를 실행하면 대기 서버에서 이 데이터베이스에 연결된 모든 사용자들의 연결을 강제로 끊는 WAL 엔트리가 생성된다. 이는 max_standby_streaming_delay와 상관 없이 바로 발생한다. ALTER DATABASE ... RENAME은 사용자와의 연결을 끊지 않는다. 데이터베이스명에 의존하는 프로그램의 경우에는 혼동이 생길 수 있다.

정상(미복원) 모드에서 연결된 사용자에 대해 DROP USERDROP ROLE을 실행하면 연결이 끊어지지 않는다. 그러나 재연결은 불가능하다. 복구 시에도 마찬가지로, 운영 서버에서 DROP USER를 실행하면 대기 서버 사용자의 연결이 끊어지지 않는다.

statistics collector은 복구 중에 활성화 된다. 모든 스캔, 읽기, 블록, 인덱스 사용 등이 대기 서버에 정상적으로 기록된다. 리플레이 과정은 운영 서버에서 반복 되지 않으므로 insert를 리플레이 해도 pg_stat_user_tables의 Inserts 칼럼이 증가되지 않는다. stats 파일은 복구 초기에 삭제되므로, 운영 서버와 대기 서버의 stats은 다르다. 이것은 특징일 뿐 버그가 아니다.

Autovacuum은 복구 중에 비활성화 된다. 복구가 끝나면 정상적으로 작동한다.

The checkpointer process and the background writer process are active during recovery. The checkpointer process will perform restartpoints (similar to checkpoints on the primary) and the background writer process will perform normal block cleaning activities. 또 대기 서버에 저장된 hint bit 정보에 대한 업데이트도 한다. CHECKPOINT 명령어는 복구 중에 수행되는데, 새로운 체크포인트가 아닌 restartpoint를 수행한다.

26.5.4. 상시 대기 관련 환경 설정 매개 변수 설명

26.5.2절26.5.3절에서 다양한 매개 변수가 언급되었다.

운영 서버에서 wal_levelvacuum_defer_cleanup_age를 사용할 수 있다. max_standby_archive_delaymax_standby_streaming_delay는 운영 서버에서 쓸 수 없다.

대기 서버에서 hot_standbymax_standby_archive_delay, max_standby_streaming_delay를 사용할 수 있다. vacuum_defer_cleanup_age는 대기 서버 모드가 아니면 쓸 수 없고, 대기 서버가 운영 서버가 되면 쓸 수 있다.

26.5.5. 주의사항

Hot Standby사용 시 몇 가지 조건이 있다. 향후 버전에서 개선될 예정이다.

  • 스냅샷을 찍기 전에 트랜잭션 수행에 대한 모든 정보가 필요하다. 부트랜잭션들을 자주 사용하는(64보다 높은 경우를 가리킴) 트랜잭션은 가장 오래 걸리는 쓰기 트랜잭션이 끝날 때까지 읽기 전용 연결 시작 시간을 늦춘다. 이런 상황이 발생할 시에는 서버 로그에 메시지가 전달 된다.

  • 대기 서버 쿼리의 유효한 starting point가 마스터 서버의 각 체크포인트에서 생성된다. 마스터 서버가 셧다운shutdown 상태일 때 대기 서버가 셧다운 되면, 마스터 서버가 WAL의 starting point를 만들기 때문에 Hot Standby 재진입이 불가능하다. 보통 마스터 서버가 셧다운되는 이유는 대기 서버가 새로운 운영 서버로 바뀌는 데 실패하기 때문이다. 마스터 서버를 의도적으로 종료할 경우, 대기 서버를 자연스럽게 새로운 마스터 서버로 만드는 것이 표준 절차이다.

  • 복구 마지막 단계에서 prepared transaction이 사용한 AccessExclusiveLocks은 평소 잠금 테이블 엔트리 수의 두 배가 필요하다. AccessExclusiveLocks이 필요한 동시적 prepared transaction을 여러 개 수행하거나 여러 AccessExclusiveLocks이 필요한 transaction을 수행하면 max_locks_per_transaction를 크게 설정하는 것이 좋다. 운영 서버의 max_locks_per_transaction의 두 배도 좋다. max_prepared_transactions의 값이 0이면 이를 전혀 고려하지 않아도 된다.

  • Serializable transaction isolation level은 hot standby에서 아직 사용할 수 없다(자세한 정보는 13.2.3절13.4.1절를 참조). 트랜잭션을 hot standby 모드에서 serializable isolation level로 설정하면 에러가 발생한다.