Как быстро диагностировать «тормоза» в PostgreSQL

GuDron

dumpz.ws
Admin
Регистрация
28 Янв 2020
Сообщения
9,447
Реакции
1,548
Credits
33,143
Как быстро диагностировать «тормоза» в PostgreSQL — без всяких внешних тулов и дополнительных логов. Только pg_stat_activity и немного здравого смысла.

Проблема: пользователи жалуются — "всё тормозит". Как понять, что именно?
Решение: открываем сессию в psql от суперпользователя и запускаем:
SQL:
SELECT pid, state, wait_event_type, wait_event, query, now() - query_start AS duration
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY duration DESC;
Что это нам даёт:
- Видим все активные (и зависшие) запросы.
- Сколько времени они уже выполняются (duration).
- На чём конкретно «висят»: CPU, IO, Lock, Client и т.д. (wait_event_type + `wait_event).
Пример:
SQL:
wait_event_type: Lock
wait_event: relation
→ Сразу ясно: кто-то держит блокировку на таблицу, и все остальные ждут.

Бонус: чтобы найти виновника, можно запустить:
SQL:
SELECT blocked_locks.pid AS blocked_pid,
       blocking_locks.pid AS blocking_pid,
       blocked_activity.query AS blocked_query,
       blocking_activity.query AS blocking_query
FROM pg_locks blocked_locks
JOIN pg_locks blocking_locks ON blocked_locks.locktype = blocking_locks.locktype
  AND blocked_locks.database IS NOT DISTINCT FROM blocking_locks.database
  AND blocked_locks.relation IS NOT DISTINCT FROM blocking_locks.relation
  AND blocked_locks.page IS NOT DISTINCT FROM blocking_locks.page
  AND blocked_locks.tuple IS NOT DISTINCT FROM blocking_locks.tuple
  AND blocked_locks.transactionid IS NOT DISTINCT FROM blocking_locks.transactionid
  AND blocked_locks.classid IS NOT DISTINCT FROM blocking_locks.classid
  AND blocked_locks.objid IS NOT DISTINCT FROM blocking_locks.objid
  AND blocked_locks.objsubid IS NOT DISTINCT FROM blocking_locks.objsubid
  AND blocked_locks.pid != blocking_locks.pid
JOIN pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted;
Этот запрос покажет, кто кого блокирует, и с каким запросом.

Это простая, но мощная техника диагностики. Поможет вам не раз в проде — особенно, когда времени мало, а багов много.

А вы пользуетесь pg_stat_activity в проде? Или сразу лезете в лог?