Есть ли тайм-аут для простаивающих соединений PostgreSQL?

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 минут.

Ответ 1

Похоже, что у вас есть утечка соединения в вашем приложении, потому что он не может закрыть пул соединений. У вас возникают проблемы не только с <idle> in transaction сеансах <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.

Ответ 2

В PostgreSQL 9.6 есть новая опция idle_in_transaction_session_timeout, которая должна выполнить то, что вы описываете. Вы можете установить его с помощью команды SET, например:

SET SESSION idle_in_transaction_session_timeout = '5min';

Ответ 3

В PostgreSQL 9.1 простаивающие соединения со следующим запросом. Это помогло мне предотвратить ситуацию, которая была гарантирована при перезапуске базы данных. Это происходит, главным образом, при подключении JDBC, открытых и не закрытых должным образом.

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

Ответ 4

если вы используете postgresql 9. 6+, то в вашем postgresql.conf вы можете установить

idle_in_transaction_session_timeout = 30000 (мсек)