PostgreSQL — алерт когда autovacuum не двигается
autovacuum_max_workers упёрлись (long-running query держит lock, или vacuum_cost_limit мал) — таблицы bloat-ятся, дисковое потребление растёт линейно. Постгрес сам не алертит.
Рецепт
#!/usr/bin/env bash
# /etc/cron.d/pg-autovacuum
# */15 * * * * postgres /opt/pg-autovacuum.sh
DB=${PGDATABASE:-postgres}
THRESH_MIN=${THRESH_MIN:-30} # alert if any vacuum runs > 30 min
OLDEST=$(psql -At -d "$DB" -c "
SELECT EXTRACT(EPOCH FROM (NOW() - query_start)) / 60
FROM pg_stat_activity
WHERE query LIKE 'autovacuum:%'
ORDER BY query_start ASC
LIMIT 1;
")
OLDEST_MIN=${OLDEST%.*}
[ -z "$OLDEST_MIN" ] && OLDEST_MIN=0
if [ "$OLDEST_MIN" -gt "$THRESH_MIN" ]; then
TABLE=$(psql -At -d "$DB" -c "
SELECT regexp_replace(query, 'autovacuum: VACUUM\s+', '')
FROM pg_stat_activity
WHERE query LIKE 'autovacuum:%'
ORDER BY query_start ASC LIMIT 1;
")
curl -fsS "$HEARTBEAT_URL" --data "vacuum_min=$OLDEST_MIN,table=$TABLE"
exit 2
fi
echo "OK (oldest vacuum=${OLDEST_MIN}m)"
То же самое в Enterno.io
Заверните в Enterno heartbeat — ловите паттерн «по понедельникам vacuum зависает на 2 ч» и target-уйте конкретный bloated-table до того, как DBA-команда среагирует.
Похожие рецепты
Таблица занимает 200 ГБ из них 150 ГБ — bloat (dead tuples). VACUUM FULL требует exclusive lock, autovacuum не справляется. Заметишь когда index-scan станет seq-scan.
Нужно ловить момент, когда реплика начала отставать от мастера больше чем на 10 секунд.
Раз в неделю аналитик запускает тяжёлую выборку без LIMIT и блокирует другие транзакции. Хочется получать уведомление через минуту, а не через час.