[postgresql] PostgreSQL 오류 : 복구 충돌로 인한 명령문 취소

대기 모드에서 PostgreSQL 데이터베이스에서 쿼리를 실행할 때 다음 오류가 발생합니다. 오류를 발생시키는 쿼리는 1 개월 동안 정상적으로 작동하지만 1 개월 이상을 쿼리하면 오류가 발생합니다.

ERROR: canceling statement due to conflict with recovery
Detail: User query might have needed to see row versions that must be removed

해결 방법에 대한 제안 사항이 있습니까? 감사



답변

핫 스탠바이 서버에서 쿼리를 실행하는 것은 다소 까다 롭습니다. 쿼리하는 동안 일부 필수 행이 기본에서 업데이트되거나 삭제 될 수 있기 때문에 실패 할 수 있습니다. 1 차측은 2 차측에서 쿼리가 시작되었음을 알지 못하므로 이전 버전의 행을 정리 (진공) 할 수 있다고 생각합니다. 그런 다음 secondary는이 정리를 재생하고 이러한 행을 사용할 수있는 모든 쿼리를 강제로 취소해야합니다.

더 긴 쿼리는 더 자주 취소됩니다.

기본 쿼리에서 더미 쿼리를 수행 한 다음 실제 쿼리가 보조 쿼리에서 실행되는 동안 유휴 상태 인 반복 가능한 읽기 트랜잭션을 시작하여이 문제를 해결할 수 있습니다. 그 존재는 기본에서 이전 행 버전을 진공 청소기로 청소하지 못하게합니다.

이 주제 및 기타 해결 방법에 대한 자세한 내용은 설명서의 핫 스탠바이-쿼리 충돌 처리 섹션에 설명되어 있습니다.


답변

만질 필요가 없습니다 hot_standby_feedback. 다른 사람들이 언급했듯이, 그것을 on부 풀릴 수 있도록 설정하면 마스터 할 수 있습니다. 슬레이브에서 트랜잭션을 열고 닫지 않는 것을 상상해보십시오.

대신, 설정 max_standby_archive_delaymax_standby_streaming_delay일부 제정신 값 :

# /etc/postgresql/10/main/postgresql.conf on a slave
max_standby_archive_delay = 900s
max_standby_streaming_delay = 900s

이렇게하면 지속 시간이 900 초 미만인 슬레이브에 대한 쿼리는 취소되지 않습니다. 워크로드에 더 긴 쿼리가 필요한 경우 이러한 옵션을 더 높은 값으로 설정하십시오.


답변

마스터에서 유휴 트랜잭션을 시작할 필요가 없습니다. postgresql-9.1 에서이 문제를 해결하는 가장 직접적인 방법은 설정하는 것입니다.

hot_standby_feedback = on

이를 통해 마스터는 장기 실행 쿼리를 인식 할 수 있습니다. 로부터 문서 :

첫 번째 옵션은 매개 변수 hot_standby_feedback을 설정하는 것입니다.이 매개 변수는 VACUUM이 최근에 죽은 행을 제거하지 못하도록하여 정리 충돌이 발생하지 않도록합니다.

이것이 기본값이 아닌 이유는 무엇입니까? 이 매개 변수는 초기 구현 후에 추가되었으며 대기가 마스터에 영향을 줄 수있는 유일한 방법입니다.


답변

여기 에 명시된 바와 같이 hot_standby_feedback = on:

글쎄, 그것의 단점은 대기가 마스터를 부 풀릴 수 있다는 것입니다. 이는 일부 사람들에게도 놀라운 일입니다.

그리고 여기 :

max_standby_streaming_delay의 설정은 무엇입니까? 오히려 기본 hot_standby_feedback보다 -1로 기본 설정합니다. 이렇게하면 대기 모드에서 수행하는 작업이 대기 모드에만 영향을 미칩니다.

그래서 나는 추가했다

max_standby_streaming_delay = -1

그리고 더 이상 pg_dump우리에게 오류가 없으며 마스터 팽창도 🙂

AWS RDS 인스턴스의 경우 http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html을 확인 하십시오.


답변

장기 대기 쿼리가 실행되는 동안 핫 스탠바이 슬레이브 서버의 테이블 데이터가 수정됩니다. 테이블 데이터가 수정되지 않도록하는 솔루션 (PostgreSQL 9.1+)은 복제를 일시 중단하고 쿼리 후에 다시 시작하는 것입니다.

select pg_xlog_replay_pause(); -- suspend
select * from foo; -- your query
select pg_xlog_replay_resume(); --resume


답변

대답하기에는 너무 늦을 수도 있지만 우리는 프로덕션에서 같은 종류의 문제에 직면합니다. 이전에는 RDS가 하나 뿐이며 앱 쪽에서 사용자 수가 증가함에 따라 읽기 전용 복제본을 추가하기로 결정했습니다. 읽기 전용 복제본이 준비에서 제대로 작동하지만 프로덕션으로 이동하면 동일한 오류가 발생합니다.

Postgres 속성에서 hot_standby_feedback 속성 을 활성화하면이 문제를 해결할 수 있습니다. 다음 링크를 참조했습니다

https://aws.amazon.com/blogs/database/best-practices-for-amazon-rds-postgresql-replication/

도움이 되길 바랍니다.


답변

위의 @ max-malysh의 훌륭한 답변에 대한 업데이트 된 정보와 참조를 추가 할 것입니다.

즉, 마스터에서 무언가를 수행하면 슬레이브에서 복제해야합니다. Postgres는이를 위해 WAL 레코드를 사용합니다.이 레코드는 마스터에서 기록 된 모든 작업 후에 슬레이브로 전송됩니다. 그런 다음 슬레이브는 작업을 실행하고 두 개는 다시 동기화됩니다. 여러 시나리오 중 하나에서 WAL 작업의 마스터에서 들어오는 내용과 슬레이브가 충돌 할 수 있습니다. 대부분의 경우 슬레이브에서 트랜잭션이 발생하여 WAL 작업이 변경하려는 항목과 충돌합니다. 이 경우 두 가지 옵션이 있습니다.

  1. WAL 조치 적용을 약간 지연시켜 슬레이브가 충돌하는 트랜잭션을 완료 한 후 조치를 적용하십시오.
  2. 슬레이브에서 충돌하는 쿼리를 취소하십시오.

우리는 # 1과 두 가지 값에 관심이 있습니다.

  • max_standby_archive_delay -이것은 현재 데이터가 아닌 WAL 아카이브에서 데이터를 읽을 때 마스터와 슬레이브 간의 긴 연결 해제 후 사용 된 지연입니다.
  • max_standby_streaming_delay -스트리밍 복제를 통해 WAL 항목이 수신 될 때 쿼리 취소에 사용되는 지연.

일반적으로 서버가 고 가용성 복제 용인 경우이 숫자를 짧게 유지하려고합니다. 기본 설정 30000(단위가 없으면 밀리 초)으로 충분합니다. 그러나 매우 오래 실행되는 쿼리가있을 수있는 아카이브,보고 또는 읽기-복제본과 같은 것을 설정하려면 취소 된 쿼리를 피하기 위해이 값을 더 높게 설정해야합니다. 900s위 의 권장 설정은 좋은 시작점처럼 보입니다. 무한한 값 -1을 좋은 아이디어로 설정하는 것에 관한 공식 문서에 동의하지 않습니다. 버그가있는 코드를 숨기고 많은 문제를 일으킬 수 있습니다.

장기 실행 쿼리 및 이러한 값을 더 높게 설정하는 한 가지 경고는 장기 실행 쿼리와 병렬로 슬레이브에서 실행중인 다른 쿼리가 장기 쿼리가 완료 될 때까지 이전 데이터를 볼 수 있다는 것입니다. 개발자는이를 이해하고 동시에 실행해서는 안되는 쿼리를 직렬화해야합니다.

방법 max_standby_archive_delaymax_standby_streaming_delay작업 및 이유에 대한 전체 설명을 보려면 여기로 이동하십시오 .