psql: FATAL: извините, слишком много клиентов уже

16

Я неожиданно получаю эту ошибку при попытке получить доступ к веб-сайту, использующему базу данных postgresql, или даже при использовании утилиты psql или pgadmin3.

Моя база данных настроена на обработку максимум 150 соединений:

# SHOW max_connections;
 max_connections 
-----------------
 150
(1 row)

После перезагрузки сервера Ubuntu, на котором работает мой веб-сайт (который действительно является единственным, использующим соединения), я вижу, что текущее количество соединений составляет 140:

# select count(*) from pg_stat_activity;
 count 
-------
   140
(1 row)

Я не понимаю, как внезапно так много подключений после перезагрузки моего сервера. Итак, я проверяю активность postgresql:

# SELECT * FROM pg_stat_activity;

И я вижу более 100 столбцов с таким же точным запросом, который выглядит следующим образом:

SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1

Еще важнее то, что все они имеют один и тот же адрес клиента (мой веб-сервер).

Этот веб-сервер использует ruby ​​на рельсах с пулом соединений 50. Несмотря на то, что существует пул соединений 50, конфигурация Apache для процесса Passenger / prefork является однопоточной, и поэтому каждый процесс не может порождать 50 потоков и 50 соединений с базой данных. Более того, это произошло после перезагрузки системы, которая сбила всех пользователей с моего веб-сервера. Вероятность состоит в том, что postgresql на сервере базы данных не знает о перезагрузке веб-сервера и все еще пытается выполнить эти запросы.

Чтобы ответить на комментарии Крейга, под колонкой ожидания отображается буква «f». Похоже, что запрос все еще выполняется, а блокировка еще не снята. Как я уже говорил ранее, странным является то, что в этом состоянии выполнения внезапно появилось более 100 запросов, идентичных друг другу в течение нескольких миллисекунд. Это для меня загадка

mydb=# SELECT * FROM pg_stat_activity;

 datid  | datname  | procpid | usesysid | usename |                                                                           current_query                                                                           | waiting |          xact_start           |          query_start          |         backend_start         |  client_addr   | client_port
--------+----------+---------+----------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------+-------------------------------+-------------------------------+-------------------------------+----------------+-------------
 464875 | mydb     |    4992 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:48.437081-04 | 2014-06-28 22:46:48.437081-04 | 2014-06-28 22:46:44.089764-04 | 192.111.11.111 |       37166
 464875 | mydb     |    4993 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:48.497764-04 | 2014-06-28 22:46:48.497764-04 | 2014-06-28 22:46:44.277856-04 | 192.111.11.111 |       37167
 464875 | mydb     |    4994 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:48.504425-04 | 2014-06-28 22:46:48.504425-04 | 2014-06-28 22:46:44.485269-04 | 192.111.11.111 |       37168
 464875 | mydb     |    4996 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:48.482695-04 | 2014-06-28 22:46:48.482695-04 | 2014-06-28 22:46:44.688203-04 | 192.111.11.111 |       37169
 464875 | mydb     |    4998 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:48.432836-04 | 2014-06-28 22:46:48.432836-04 | 2014-06-28 22:46:44.703883-04 | 192.111.11.111 |       37170

-- many more

 464875 | mydb     |    5052 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:59.584386-04 | 2014-06-28 22:46:59.584386-04 | 2014-06-28 22:46:51.85682-04  | 192.111.11.111 |       37360
 464875 | mydb     |    5053 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:59.506483-04 | 2014-06-28 22:46:59.506483-04 | 2014-06-28 22:46:52.083316-04 | 192.111.11.111 |       37367
 464875 | mydb     |    8958 |    16387 | myuser | <IDLE>                                                                                                                                                            | f       |                               | 2014-06-29 00:05:06.735249-04 | 2014-06-27 16:34:39.307312-04 | 192.111.11.111 |       52759
 464875 | mydb     |    5054 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:59.52573-04  | 2014-06-28 22:46:59.52573-04  | 2014-06-28 22:46:52.285867-04 | 192.111.11.111 |       37371
 464875 | mydb     |    5055 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:59.530804-04 | 2014-06-28 22:46:59.530804-04 | 2014-06-28 22:46:52.303562-04 | 192.111.11.111 |       37372
 464875 | mydb     |    5056 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:59.572198-04 | 2014-06-28 22:46:59.572198-04 | 2014-06-28 22:46:52.31447-04  | 192.111.11.111 |       37373
 464875 | mydb     |    5057 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:59.872037-04 | 2014-06-28 22:46:59.872037-04 | 2014-06-28 22:46:52.323721-04 | 192.111.11.111 |       37374
 464875 | mydb     |    5058 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:59.961803-04 | 2014-06-28 22:46:59.961803-04 | 2014-06-28 22:46:52.334238-04 | 192.111.11.111 |       37375
 464875 | mydb     |    5059 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:59.53713-04  | 2014-06-28 22:46:59.53713-04  | 2014-06-28 22:46:52.347227-04 | 192.111.11.111 |       37376
 464875 | mydb     |    5060 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:47:00.208948-04 | 2014-06-28 22:47:00.208948-04 | 2014-06-28 22:46:52.360008-04 | 192.111.11.111 |       37377
 464875 | mydb     |    5061 |    16387 | myuser | SELECT  "reports".* FROM "reports"  WHERE (("reports"."time" < '2014-06-28 13:30:42.000000' AND "reports"."unit_id" = 3192)) ORDER BY "reports"."id" DESC LIMIT 1 | f       | 2014-06-28 22:46:59.938983-04 | 2014-06-28 22:46:59.938983-04 | 2014-06-28 22:46:52.369496-04 | 192.111.11.111 |       37378
JohnMerlino
источник
Посмотрите на pg_stat_activity.backend_start. Были ли эти подключения созданы до или после перезагрузки веб-сервера? Если это все новые подключения, я думаю, это означает, что проблема на стороне веб-сервера.
Ник Барнс
@NickBarnes все эти соединения имеют один и тот же запрос в столбце «current_query», а время backend_start практически одинаково для всех из них (с интервалом в миллисекунды). Вот что странно, и я верю, что если память мне не изменяет, все они были до перезагрузки. Но я предполагал, что перезагрузка разорвет связь.
ДжонМерлино
1
Хорошо ... Возможно, вам придется проверить topна сервере, чтобы увидеть, заняты ли эти процессы. Если это так, то я думаю, что соединения должны исчезнуть после завершения запросов (или, наоборот, вы можете просто убить их сейчас). Если они бездействуют, а соединения определенно мертвы, тогда я не уверен, что происходит или как это предотвратить в следующий раз ...
Ник Барнс
1
Проверьте waitingфлаг pg_stat_activity, посмотрите, не застряли ли они в замке.
Крейг Рингер
1
Вывод, который вы вставили, SELECT * FROM pg_stat_activity;не правдоподобен - колонок недостаточно. Что говорит столбец состояния? Это самое важное поле для этого вопроса.
Эрадман

Ответы:

5

Это, кажется, специфическая проблема клиентского программирования. Вы не сможете исправить это, например, подняв параметр "max_connections".

Я обнаружил возможную связанную проблему: пул соединений с базой данных Ruby

Несмотря на то, что вы также можете выполнить еще одну отладку на стороне сервера:

Включите «log_connections» и «log_disconnections». Также используйте «log_line_prefix» с «% m% a% p».

Очень полезные приложения для отладки серверов PostgreSQL имеют Powa или намного больше, например: pg_activity

Для отладки сервера в реальном времени я предпочитаю pg_activity - особенно с его возможностью отображать блокировщики и убивать сессии.

Йозеф Хопфгартнер
источник
-4

Это лучший способ решить проблему ... это работает

Войдите на сервер, используя SSH putty,

sudo /etc/init.d/postgresql stop

это убивает мертвые журналы процессов в базе данных,

sudo /etc/init.d/postgresql start

Maduka
источник
6
А потом в следующий раз вы снова остановите производственный сервер? Ваше решение четко устраняет застрявшие процессы, но не объясняет, почему они существуют, и не является устойчивым.
Дезсо