Долгие запросы могут вызвать серьёзные проблемы с производительностью PostgreSQL. Рассказываем, как автоматизировать их завершение.
Зачем убивать долгие запросы?
На практике такие запросы могут:
- Блокировать таблицы и строки
- Съедать память и процессор
- Вызывать дедлоки
- Мешать миграциям или мониторингу
Причины:
- Пропущенные
WHERE
-условия - Сложные отчёты
- Подвисшие клиенты
Как работает скрипт
Мы используем Bash-скрипт для:
- Подключения к PostgreSQL
- Поиска запросов старше 60 секунд
- Автоматического завершения этих запросов
Скрипт для завершения долгих запросов
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 | Запускает скрипт по расписанию |