Чи є тайм-аут для простоїв з'єднань PostgreSQL?


94
1 S postgres  5038   876  0  80   0 - 11962 sk_wai 09:57 ?        00:00:00 postgres: postgres my_app ::1(45035) idle                                                                                 
1 S postgres  9796   876  0  80   0 - 11964 sk_wai 11:01 ?        00:00:00 postgres: postgres my_app ::1(43084) idle             

Я їх бачу багато. Ми намагаємось усунути витік з’єднання. Але тим часом ми хочемо встановити час очікування для цих простоїв, можливо, максимум до 5 хвилин.


як ви підключаєтесь до БД? socketTimeout може бути тим, що ви шукаєте.
Doon

У нас є ця застаріла веб-програма Pylons, і ми використовували SQLAlchemy, але, мабуть, не використовували її належним чином. Я не пам’ятаю. Ми намагаємось усунути витік. socketTimeoutЗ документа, схоже, це повністю закриває з'єднання з БД. Я намагаюся закрити кожну неробочу діяльність, і лічильник запускається, як тільки встановлено з'єднання.
user1012451


@ user1012451 Коли ви говорите "закрити кожен простій" - ви маєте на увазі припинити <IDLE> in transactionсеанси, залишивши сеанс запущеним, але в <IDLE>стані? Іншими словами, розірвати транзакцію, але не сеанс? (Проголосовало проти: незрозуміле питання)
Крейг Рінгер,

@CraigRinger через деякий час ми досягаємо максимального підключення до клієнта. Щоб вирішити це, ми повинні перезапустити веб-програму, яка змушує також перезапустити postgresql. Це знищить усі зв’язки. Коли ми бачимо їх idleназавжди, ми запитуємо, чи можемо ми встановити час очікування для кожного з’єднання / сеансу (я, чесно кажучи, не знаю правильної термінології, вибачте). Якщо транзакція займає 5 хвилин для звичайної веб-програми, щось має бути не так ....
user1012451

Відповіді:


118

Здається, у вашому додатку витік з’єднання, оскільки він не може закрити об’єднані з’єднання . У вас виникають проблеми не лише із <idle> in transactionсеансами, але й із загальною кількістю зв’язків.

Вбивство зв’язків - це не правильна відповідь, але це тимчасовий обхідний спосіб.

Замість того, щоб повторно запускати PostgreSQL для завантаження всіх інших з'єднань з бази даних PostgreSQL, див.: Як я можу від'єднати всіх інших користувачів від бази даних postgres? та Як скинути базу даних PostgreSQL, якщо до неї є активні підключення? . Останній показує кращий запит.

Для встановлення тайм-аутів, як запропонував @Doon, див. Розділ Як автоматично закрити недіючі з’єднання в PostgreSQL? , який радить вам використовувати PgBouncer для проксі для PostgreSQL та керування простоями з'єднань. Це дуже гарна ідея, якщо у вас є програма для виправлення помилок, яка все одно витікає з підключень; Я настійно рекомендую налаштувати PgBouncer.

TCP KeepAlive не робитиме цю роботу тут, тому що додаток все ще підключений і живий, він просто не повинно бути.

У PostgreSQL 9.2 і вище ви можете використовувати новий state_change стовпець часової позначки та stateполе pg_stat_activityдля реалізації неробочого з’єднання. Попросіть роботу cron виконати щось подібне:

SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'regress'
      AND pid <> pg_backend_pid()
      AND state = 'idle'
      AND state_change < current_timestamp - INTERVAL '5' MINUTE;

У старих версіях потрібно застосовувати складні схеми, які відстежують час простою з’єднання. Не докучай; просто використовуйте pgbouncer.


4
Добре, але це призведе до знищення інших фонових програм PgAdmin. Використовуйте додаткову умову application_name = ''
Ендрю Селіванов

1
Чи можу я запустити pg_terminate_backend, якщо я використовую pgbouncer?
Henley Chiu

@HenleyChiu Я не розумію, чому ні, хоча я спеціально не перевіряв.
Крейг Рінгер,

1
Запуск цього, здається, вбив мого процесу відправника WAL
Джозефа Персі

@CraigRinger навіть підключення psql вважається бездіяльним з'єднанням. І чому спочатку потрібно розірвати зв’язок простою. У мене є тривалий код, який встановлює зв'язок з pg, виконує деяку операцію dml, а потім чекає повідомлення через чергу, а потім виконує ще деяку операцію dml. навіть тоді зв'язок з поштовими відправленнями є idle. чому я повинен закривати його.
Вірен

72

У PostgreSQL 9.6 є нова опція, idle_in_transaction_session_timeoutяка повинна виконати те, що ви описуєте. Ви можете встановити його за допомогою SETкоманди, наприклад:

SET SESSION idle_in_transaction_session_timeout = '5min';

1
Дуже просто запитувати щось настільки просте, але я взагалі абсолютно новий у базах даних - чи не могли б ви навести дуже базовий приклад того, як користуватися цією функцією?
sg

Щось подібне у попередніх версіях PostgreSQL ??
sdsc81

Ні, для попередніх версій потрібно щось подібне до інших відповідей.
шості

Чи потрібно встановлювати цей параметр при кожному перезапуску бази даних? Або після того, як ви це зробили, ви можете забути про це? Дякую
fresko

5
SET SESSIONпризначений лише для поточного сеансу (він повернеться за замовчуванням після відкриття нового з’єднання). Ви також можете встановити параметри конфігурації на рівні бази даних, використовуючи, наприклад ALTER DATABASE SET idle_in_transaction_session_timeout = '5min', або використовуючи конфігураційні файли (див. Postgresql.org/docs/current/static/config-setting.html ).
шості

22

У PostgreSQL 9.1, простої з'єднання з наступним запитом. Це допомогло мені запобігти ситуації, яка вимагала перезапуску бази даних. Це трапляється здебільшого з відкритими та не закритими належним чином з'єднаннями JDBC

SELECT
   pg_terminate_backend(procpid)
FROM
   pg_stat_activity
WHERE
   current_query = '<IDLE>'
AND
   now() - query_start > '00:10:00';

1
pg_terminate_backend працює з 8.4
Ендрю Бенкс,

8

якщо ви використовуєте postgresql 9.6+, то у своєму postgresql.conf ви можете встановити

idle_in_transaction_session_timeout = 30000 (мс)


0

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

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