Была такая проблема. С периодичностью раз в месяц web-приложение останавливалось с ошибкой 502. Причина - postgresql переставал обрабатывать запросы, потому что был превышен лимит количества соединений. Список процессов показывал кучу открытых ожидающих соединений, которые блокировались каким-то запросом. Причём запрос был вполне рядовой, который обычно выполнялся мгновенно. Причину, которая приводила к такой блокировке, выяснить не хватило ума. Но было несколько процессов "idle in transaction", и после убивания одного из них всё восстанавливалось.
В postgresql 9.5 ещё нет опции, устанавливающей таймаут на висячие транзакции. Поэтому было решено установить Pgbouncer.
В итоге есть postgresql, перед ним pgbouncer в pool_mode=transaction.
Пару недель всё работало замечательно. Но в течение последних двух дней вдруг без всякой видимой причины образовалась проблема. Web-приложение возвращает пользователю 500, пользователь удивляется, пробует ещё раз, всё опять работает нормально. Через несколько минут, уже в другом месте приложения, ситуация повторяется. Пользователь нервничает.
В логе приложения (Python, Flask, psycopg2):
Exception on /any-url-of-the-application [POST]
...
...
Exception: idle transaction timeout
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
Смотрю, на каких запросах падает - на любых, которые в обычной ситуации отрабатывают мгновенно.
В pgbouncer.ini:
idle_transaction_timeout = 600
Нагрузка на сервер - 10-20 соединений в секунду. В системных логах, в логах Postgresql и Pgbouncer - нет ничего подозрительного. Список процессов не показывает наличие процессов postgres с висящими транзакциями. Какие системные всплески, приводящие к кратковременному исчерпанию ресурсов, которые могут приводить к такой специфической ошибке - ума не приложу.
Странно вот что. Если бы такая ошибка возникала в обслуживающих скриптах, выполняющих длинные регулярные задачи в cron, было бы понятно, где копать. А тут - простой юзер, работает себе в браузере, и вдруг после очередного клика на кнопке - ошибка 500! idle_transaction_timeout = 600 - это 10 минут. Юзер же получает 500 мгновенно. Если учесть, что он при каждом обновлении страницы создаёт в контексте Flask-приложения своё собственное соединение, как оно может вдруг упасть по причине idle transaction timeout?
Что это может быть?