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

Любые предложения о том, как решить? Спасибо

5 ответов

Решение

Выполнение запросов на сервере с горячим резервированием несколько сложно - это может привести к сбою, поскольку во время запроса некоторые необходимые строки могут быть обновлены или удалены на первичном сервере. Поскольку первичный сервер не знает, что запрос запущен на вторичном сервере, он считает, что может очистить (очистить) старые версии своих строк. Затем вторичный сервер должен воспроизвести эту очистку и принудительно отменить все запросы, которые могут использовать эти строки.

Более длинные запросы будут отменяться чаще.

Вы можете обойти это, запустив повторяющуюся транзакцию чтения на первичном сервере, который выполняет фиктивный запрос, а затем бездействует, пока реальный запрос выполняется на вторичном сервере. Его наличие предотвратит очистку старых версий рядов от первичных.

Подробнее об этом и других обходных путях рассказывается в разделе " Горячий резерв - обработка конфликтов запросов " в документации.

Не нужно трогать hot_standby_feedback, Как уже упоминалось, установка его на on может раздувать мастер. Представьте, что вы открываете транзакцию на подчиненном устройстве, а не закрываете ее.

Вместо этого установите max_standby_archive_delay а также max_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? Я бы предпочел по умолчанию это -1, чем по умолчанию hot_standby_feedback on. Таким образом, то, что вы делаете в режиме ожидания, влияет только на режим ожидания.


Итак, я добавил

max_standby_streaming_delay = -1

И не более pg_dump ошибка для нас, ни мастер блат:)

Для экземпляра AWS RDS, проверьте http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html

Я собираюсь добавить обновленную информацию и ссылки на отличный ответ @max-malysh выше.

Короче говоря, если вы что-то делаете на мастере, это нужно реплицировать на подчиненном. Postgres использует для этого записи WAL, которые отправляются подчиненному после каждого зарегистрированного действия на ведущем устройстве. Затем ведомое устройство выполняет действие, и оба снова синхронизируются. В одном из нескольких сценариев вы можете вступить в конфликт на ведомом устройстве с тем, что поступает от ведущего устройства в действии WAL. В большинстве из них на ведомом устройстве происходит транзакция, которая конфликтует с тем, что действие WAL хочет изменить. В этом случае у вас есть два варианта:

  1. Задержите на некоторое время применение действия WAL, позволяя ведомому устройству завершить конфликтующую транзакцию, затем примените действие.
  2. Отмените конфликтующий запрос на ведомом устройстве.

Нас интересует №1 и два значения:

  • max_standby_archive_delay - это задержка, используемая после длительного отключения между ведущим и ведомым, когда данные считываются из архива WAL, который не является текущими данными.
  • max_standby_streaming_delay - задержка, используемая для отмены запросов при получении записей WAL посредством потоковой репликации.

Как правило, если ваш сервер предназначен для репликации с высокой доступностью, вы хотите, чтобы эти цифры были короткими. По умолчанию30000(миллисекунд, если единицы не указаны) достаточно для этого. Если, однако, вы хотите настроить что-то вроде архива, реплики для отчетов или чтения, которые могут иметь очень длительные запросы, тогда вам нужно установить это значение выше, чтобы избежать отмененных запросов. Рекомендуемый900sнастройка выше кажется хорошей отправной точкой. Я не согласен с официальными документами по установке бесконечного значения-1 как хорошая идея - это может замаскировать некоторый ошибочный код и вызвать множество проблем.

Единственное предостережение относительно длительных запросов и установки этих значений выше заключается в том, что другие запросы, выполняющиеся на ведомом устройстве параллельно с длительным запросом, вызывающим задержку действия WAL, будут видеть старые данные до тех пор, пока длинный запрос не будет завершен. Разработчики должны понимать это и сериализовать запросы, которые не должны выполняться одновременно.

Для полного объяснения того, как max_standby_archive_delay а также max_standby_streaming_delayработа и почему, иди сюда.

Данные таблицы на подчиненном сервере с горячим резервированием изменяются во время выполнения длинного запроса. Решение (PostgreSQL 9.1+), чтобы убедиться, что данные таблицы не изменены, - приостановить репликацию и возобновить работу после запроса:

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

Возможно, уже слишком поздно для ответа, но мы сталкиваемся с той же проблемой при производстве. Раньше у нас был только один RDS, и по мере увеличения количества пользователей на стороне приложения мы решили добавить для него реплику чтения. Реплика чтения работает правильно на промежуточном этапе, но как только мы перешли в производство, мы начинаем получать ту же ошибку.

Поэтому мы решаем эту проблему, включив свойство hot_standby_feedback в свойствах Postgres. Мы сослались на следующую ссылку

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

Надеюсь, это поможет.

Аналогичным образом, вот второе предостережение в отношении разработки @Artif3x отличного ответа @max-malysh, оба выше.

При любом отложенном применении транзакций от мастера последователи будут иметь более старое устаревшее представление данных. Поэтому, предоставляя время для завершения запроса на подписчике путем установки max_standby_archive_delay и max_standby_streaming_delay, имеет смысл, имейте в виду оба этих предупреждения:

Если значение подписчика для резервного копирования слишком сильно противоречит запросам хостинга, одним из решений будет несколько последователей, каждый из которых оптимизирован для одного или другого.

Также обратите внимание, что несколько запросов подряд могут вызывать задержку применения записей wal. Поэтому при выборе новых значений это не просто время для одного запроса, а движущееся окно, которое начинается всякий раз, когда начинается конфликтующий запрос, и заканчивается, когда наконец применяется запись wal.

Другие вопросы по тегам