В php пример этой выглядит как следующее сообщение:
PDOException: SQLSTATE[08006] [7] connection to server at «127.0.0.1», port 5433 failed: извините, уже слишком много клиентов connection to server at «127.0.01», port 5433 failed: ВАЖНО: извините, уже слишком много клиентов в функции Drupal\ClassResolver::resolve() (строка 29 в файле …).
У вас это может быть какая то другая точка в коде, с PHP проблема не связана.
Эта ошибка означает, что ваш сайт/приложение не может подключиться к базе данных PostgreSQL, так как превышен лимит одновременных подключений. Сообщение «извините, уже слишком много клиентов» — это прямой перевод ошибки PostgreSQL FATAL: sorry, too many clients already.
Основной источник проблемы — это т.н. зависшие соединения, т.е. idle или idle in transaction.
Их список можно посмотреть следующим запросом:
|
1 2 3 |
SELECT pid, usename, datname, state, state_change, query FROM pg_stat_activity WHERE state = 'idle'; |
Сами по себе idle соединения — не являются чем то плохим. Это открытые соединения с базой данных, которые открывает приложение на момент запроса / сайт при инициализации скриптов, подключаясь к базе данных. Они должны закрываться PHP автоматически (в других языках это может быть реализовано иначе).
Если они висят в таком состоянии в течении периода времени больше адекватного значения, например 15 мин, то вероятно это idle состояние является подвисшим процессом и штатно не было завершено.
Когда их количество достигает максимально разрешенного в конфигурации postgres, то сервер отказывает принимать новые соединения.
Действующий лимит можно посмотреть следующим образом:
|
1 |
SELECT name, setting, pending_restart<br>FROM pg_settings<br>WHERE name = 'max_connections'; |
Типовое значение — 100. Это не очень много, может быть и 1000 и более. Но если у вас не хватает кол-ва соединений (превышается лимит), высоконагруженное приложение, то обычно создают кластер из серверов баз данных, распределяя соединения в этом пуле.
Что делать с подвисшими соединениями?
Можно попробовать их завершить принудительно:
|
1 2 3 4 |
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle' AND state_change < now() - '15 minuntes'::interval; |
Так вы закроете все idle соединения, которые открыты более чем 15 минут назад.
Другой вариант: увеличить число max_connections.
|
1 |
ALTER SYSTEM SET max_connections = 500; |
Или установив в конфиг файле — postgresql.conf
|
1 |
max_connections = 500 |
И обязательно сделать сделать перезапуск демона для актуализации настоек. У настроек разный приоритет, который следует учитывать.
|
1 |
sudo systemctl restart postgresql |
Для мониторинга может быть полезным собрать информацию о лимитах и типах соединений одним запросом:
|
1 2 3 4 5 6 7 8 9 10 |
SELECT (SELECT setting::int FROM pg_settings WHERE name = 'max_connections') AS max_conn, (SELECT setting::int FROM pg_settings WHERE name = 'superuser_reserved_connections') AS reserved, count() AS used, count() FILTER (WHERE state = 'active') AS active, count() FILTER (WHERE state = 'idle') AS idle, count() FILTER (WHERE state = 'idle in transaction') AS idle_in_tx, count() FILTER (WHERE state = 'idle in transaction (aborted)') AS idle_in_tx_aborted, (SELECT setting::int FROM pg_settings WHERE name = 'max_connections') - count() AS free FROM pg_stat_activity |



