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


139

대기 모드에서 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

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


그것은 또한 솔루션이이 오류에 언급 된 AWS의 문서를 검색 할 aws.amazon.com/blogs/database/...을
arunjos007

답변:


89

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

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

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

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


10
PostgreSQL 9.1+ 사용자 : 실제 솔루션은 아래 eradman 의 답변을 참조하십시오 .
Zoltán

3
PostgreSQL 9.1+ 사용자에게는 max-malysh의 답변이 훨씬 안전합니다. 위험을 이해하지 않으면 eradman 제안을 수행하지 마십시오.
Davos

91

만질 필요가 없습니다 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 초 미만인 슬레이브에 대한 쿼리는 취소되지 않습니다. 워크로드에 더 긴 쿼리가 필요한 경우 이러한 옵션을 더 높은 값으로 설정하십시오.


1
이것이 우리가 사용한 솔루션입니다. 여기에 제시된 모든 옵션 중에서 가장 좋은 타협 인 것 같습니다.
mohit6up

2
이것이 가장 좋은 대답입니다. 문서에 따라 이들은 누적됩니다. 복제를 유지하는 복제본에 여러 쿼리가있는 경우 899에 도달하면 다른 2 초 쿼리가 취소 될 수 있습니다. 코드에서 지수 백 오프를 구현하는 것이 가장 좋습니다. 또한 복제가 스트리밍되는 동안 스트리밍 지연이 적용됩니다. 복제가 스트리밍을 유지할 수없는 경우 아카이브에서 복제로 이동합니다. 아카이브에서 복제하는 경우에는이를 따라 잡아야 max_standby_archive_delay하며 다른 것보다 작아야 할 수도 있습니다.
Davos

2
이것이 여전히 최고의 솔루션입니다. Redshift에서는 파라미터 그룹 설정을 통해이를 설정할 수 있습니다 ms. 즉 900s = 16 분 = 900000ms 여야합니다.
NullDev

GCP에이를 업데이트하려면,도에서 수행 ms cloud.google.com/sql/docs/postgres/...
howMuchCheeseIsTooMuchCheese

대기 목적이 예를 들어보고를위한 것이며 장애 조치를 처리 할 준비가되어있는 핫 대기가 아니라면 이것이 최선의 대답입니다.
soupdog

77

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

hot_standby_feedback = on

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

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

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


11
이 매개 변수는 대기에서 설정해야합니다.
Steve Kehlet

3
이 경우 마스터에게는 몇 가지 단점이 있습니다. Hot-Standby-Feedback
Evgeny Liskovets

50

여기 에 명시된 바와 같이 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을 확인 하십시오.


1
@ lennard, 이것은 나를 위해 일했습니다. 슬레이브의 postgresql.conf에이 구성을 추가 한 다음 슬레이브를 다시 시작했습니다.
Ardee Aram

13
물론 이러한 방식으로 무한 복제 지연이 발생할 수 있습니다. 또한 복제 슬롯을 사용하여 복제본을 마스터에 연결하는 경우 마스터에서 과도한 xlog 보존이 발생할 수 있으므로 WAL 보관을 사용하는 경우에만 실제로 실행 가능합니다.
Craig Ringer

7
AWS RDS에서이를 어떻게 설정합니까?
Kris MP

1
@KrisMP psql 사용
Yehonatan

4
파라미터 그룹의 @KrisMP-docs.aws.amazon.com
AmazonRDS

13

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

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

1
수퍼 유저 권한이 필요합니다. 따라서 어떤 경우에는 해결책이 아닐 수도 있습니다.
Joao Baltazar

1
PostgreSQL 10에서는 xlog으로 교체 wal되었으므로 pg_wal_replay_pause()및 을 호출하려고합니다 pg_wal_replay_resume().
울리십시오

3

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

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

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

도움이 되길 바랍니다.


2

위의 @ 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작업 및 이유에 대한 전체 설명을 보려면 여기로 이동하십시오 .


1

마찬가지로 위의 @ max-malysh의 탁월한 답변에 대한 @ Artif3x 정교화에 대한 두 번째 경고가 있습니다.

마스터의 트랜잭션 적용이 지연되면 추종자들은 오래된 오래된 데이터 뷰를 갖게됩니다. 따라서 max_standby_archive_delay 및 max_standby_streaming_delay를 설정하여 팔로어에 대한 쿼리를 완료 할 시간을 제공하는 동안 다음 두 가지주의 사항을 명심하십시오.

백업 팔로어의 값이 쿼리 쿼리와 충돌하는 결과가 너무 크면 한 솔루션은 여러 팔로어가 될 수 있으며 각 솔루션은 서로 최적화되어 있습니다.

또한 행에있는 여러 쿼리로 인해 월 항목 적용이 계속 지연 될 수 있습니다. 따라서 새 값을 선택할 때는 단일 쿼리의 시간뿐만 아니라 충돌하는 쿼리가 시작될 때마다 시작하고 월마트 항목이 마지막으로 적용되면 종료되는 이동 창입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.