Долгие запросы могут вызвать серьёзные проблемы с производительностью PostgreSQL. Рассказываем, как автоматизировать их завершение.

Зачем убивать долгие запросы?

На практике такие запросы могут:

  • Блокировать таблицы и строки
  • Съедать память и процессор
  • Вызывать дедлоки
  • Мешать миграциям или мониторингу

Причины:

  • Пропущенные WHERE-условия
  • Сложные отчёты
  • Подвисшие клиенты

Как работает скрипт

Мы используем Bash-скрипт для:

  1. Подключения к PostgreSQL
  2. Поиска запросов старше 60 секунд
  3. Автоматического завершения этих запросов

Скрипт для завершения долгих запросов

1. Переменные подключения

#!/bin/bash

PG_CONN="postgres://user:pass@postgres-host/postgres-db"
QUERY_TIMEOUT="60"
PSQL_RUN="psql $PG_CONN -Atc"

2. SQL-запрос

QUERY="SELECT pid FROM pg_stat_activity WHERE now() - query_start > '${QUERY_TIMEOUT} seconds'::interval"

3. Завершение

echo "Ищем запросы дольше $QUERY_TIMEOUT секунд..."
pids=$(${PSQL_RUN} "$QUERY")

for pid in $pids; do
  echo "Завершаем PID $pid..."
  ${PSQL_RUN} "SELECT pg_terminate_backend($pid)"
done

Автоматизация через Cron

Чтобы запускать каждые 5 минут:

*/5 * * * * /path/to/kill-long-queries.sh >> /var/log/pg_kill.log 2>&1

Рекомендации

  • Исключайте критичные процессы: AND application_name NOT LIKE 'pg_monitor%'
  • Используйте pg_cancel_backend(pid) для мягкой отмены
  • Убедитесь в наличии прав для завершения процессов

Вывод

Автоматическое завершение зависших запросов избавляет от простоя и сбоев в системе.

ИнструментНазначение
pg_stat_activityПоказывает активные запросы
pg_terminate_backendУбивает указанный запрос
CronЗапускает скрипт по расписанию