Помилка PostgreSQL: скасування заяви через конфлікт із відновленням


139

Я отримую таку помилку під час запуску запиту на db 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

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

Більш часті запити будуть скасовуватися частіше.

Ви можете обійти це, запустивши повторювану транзакцію читання на основній, яка робить фіктивний запит, а потім сидить в режимі очікування, коли реальний запит виконується на вторинному. Його наявність запобіжить пилосос старих версій рядків на первинних.

Більше про цю тему та інші шляхи вирішення пояснюється в розділі « Гарячий режим очікування» - «Обробка конфліктів запитів» у документації.


10
Користувачам PostgreSQL 9.1+: див. Відповідь eradman нижче для практичного рішення.
Золтан

3
Для користувачів PostgreSQL 9.1+: відповідь max-malysh набагато безпечніше. Не робіть пропозиції ерадмана, якщо ви не розумієте ризиків.
Давос

91

Не потрібно чіпати 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 секунд не будуть скасовані. Якщо ваше навантаження вимагає більш довгих запитів, просто встановіть ці параметри на більш високе значення.


1
Це рішення, яке ми закінчили. Здається, найкращий компроміс між усіма представленими тут варіантами.
mohit6up

2
Це найкраща відповідь. Зверніть увагу на документи, вони є сукупними; якщо у вас є кілька запитів на репліку, що затримує реплікацію, то, можливо, ви перейдете до 899, тоді ще 2 секунди запиту скасовуються. Найкраще просто застосувати деякий експоненціальний відступ у своєму коді. Також затримка потоку діє під час реплікації. Якщо реплікація не може йти в ногу з потоковою передачею, вона перейде до реплікації з архіву. Якщо ви реплікуєте з архіву, ви, ймовірно, повинні дозволити його наздогнати, max_standby_archive_delayможливо, він повинен бути меншим за інші.
Давос

2
Це все-таки найкраще рішення. Візьміть до уваги, що в Redshift ви можете встановити це за допомогою параметрів групи параметрів, тільки щоб воно було в ms, тобто 900s = 16 хвилин = 900000ms.
NullDev

Щоб оновити це на GCP, також зроблено в ms cloud.google.com/sql/docs/postgres/…
howMuchCheeseIsTooMuchCheese

За умови, що мета очікування - наприклад, звітування, і це не гарячий режим очікування, який потрібно бути готовим до роботи з відмовою, це абсолютно найкраща відповідь.
суп-кор

77

Немає необхідності запускати непрацюючі транзакції на майстер. У postgresql-9.1 найбільш прямим способом вирішення цієї проблеми є встановлення

hot_standby_feedback = on

Це дасть зрозуміти майстру про тривалі запити. З документів :

Перший варіант - встановити параметр hot_standby_feedback, який запобігає видаленню нещодавно відмерлих рядків VACUUM і не виникає конфліктів очищення.

Чому це не за замовчуванням? Цей параметр був доданий після первинної реалізації, і це єдиний спосіб, коли очікування може вплинути на головного.


11
Цей парам повинен бути встановлений у режимі очікування.
Стів Келет

3
Є кілька недоліків для господаря в цій справі " Гарячі очікування-зворотній зв'язок"
Євген Лісковець

50

Як сказано тут про hot_standby_feedback = on:

Ну, і недоліком є ​​те, що в режимі очікування можна роздути господаря, що може здивувати і деяких людей

І ось :

З якою настройкою max_standby_streaming_delay? Я вважаю за краще за замовчуванням до -1, ніж за замовчуванням hot_standby_feedback увімкнено. Таким чином, те, що ви робите в режимі очікування, впливає лише на режим очікування


Тому я додав

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 підлеглого, а потім перезапустив підлеглий.
Арді Арам

13
Звичайно, ви можете отримати відставання без обмежених копій таким чином. І якщо ви використовуєте слот для реплікації для підключення репліки до master, це може призвести до надмірного утримання xlog на master, тому це дійсно життєздатно лише якщо ви використовуєте WAL-архівування.
Крейг Рінгер

7
Як встановити це на AWS RDS?
Kris MP

1
@KrisMP Використання PSQL
Йехонатан

4
@KrisMP в групі параметрів - docs.aws.amazon.com/AmazonRDS/latest/UserGuide/…
r3m0t

13

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

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

1
Для цього потрібні права суперкористувача. Тож це може не бути рішенням у деяких випадках.
Жоао Балтазар

1
У PostgreSQL 10 xlogйого замінили wal, так що ви хочете зателефонувати pg_wal_replay_pause()і pg_wal_replay_resume().
19

3

Для відповіді це може бути пізно, але ми стикаємося з тим же питанням, що стосується виробництва. Раніше у нас було тільки одне RDS, і оскільки кількість користувачів збільшується на стороні програми, ми вирішили додати для нього Read Replica. Прочитана репліка справно працює на постановці, але як тільки ми перейшли до виробництва, ми починаємо отримувати ту саму помилку.

Тому ми вирішуємо це, включивши властивість hot_standby_feedback у властивості Postgres. Ми послали наступне посилання

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 як хорошої ідеї - це може замаскувати якийсь баггі-код і спричинити багато проблем.

Одне застереження щодо довготривалих запитів та встановлення цих значень вище - це те, що інші запити, що працюють на підлеглому, паралельно довгого запущеного, який спричиняє затримку дії WAL, бачитимуть старі дані, поки довгий запит не буде завершений. Розробникам необхідно зрозуміти це і послідовно виконувати запити, які не повинні працювати одночасно.

Для повного пояснення того, як max_standby_archive_delayі як max_standby_streaming_delayпрацювати і навіщо, перейдіть сюди .


1

Так само, ось другий застереження до розробки @ Artif3x відмінної відповіді @ max-malysh, як вище.

При будь-якому відкладеному застосуванні транзакцій від головного розпорядника послідовники (ів) матимуть старіший, застарілий вигляд даних. Тому, надаючи час для завершення запиту підписника, встановивши max_standby_archive_delay та max_standby_streaming_delay, має сенс, пам’ятайте про обидва ці застереження:

  • значення послідовника у режимі очікування / резервного копіювання зменшується
  • будь-які інші запити, що виконуються на послідовнику, можуть повернути несвіжі дані .

Якщо значення послідовника для резервного копіювання виявляється занадто сильним в конфлікті з хостинг-запитами, одним рішенням буде кілька підписників, кожен оптимізований під той чи інший.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.