Как просмотреть список replication slots в PostgreSQL?

«Как просмотреть список replication slots в PostgreSQL?» — вопрос из категории Базы данных, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Replication slots в PostgreSQL — это механизм, который гарантирует, что WAL-логи (Write-Ahead Logs) не будут удалены до тех пор, пока они не будут получены всеми репликами. Их мониторинг критически важен для предотвращения заполнения диска.

1. Основной запрос для просмотра слотов:

-- Показать все слоты репликации с основной информацией
SELECT * FROM pg_replication_slots;

-- Структурированный вывод с ключевыми метриками
SELECT 
    slot_name,
    plugin,
    slot_type,
    active,
    pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS replication_lag_bytes,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS lag_pretty,
    confirmed_flush_lsn,
    restart_lsn,
    wal_status,
    safe_wal_size
FROM pg_replication_slots
ORDER BY replication_lag_bytes DESC NULLS LAST;

2. Мониторинг лага репликации:

-- Лаг в байтах для каждого слота
SELECT 
    slot_name,
    pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS lag_bytes,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS lag_human
FROM pg_replication_slots
WHERE active = true;

-- Мониторинг с предупреждениями (для интеграции в системы мониторинга)
SELECT 
    slot_name,
    CASE 
        WHEN pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) > 1073741824 THEN 'CRITICAL: >1GB lag'
        WHEN pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) > 536870912 THEN 'WARNING: >512MB lag'
        ELSE 'OK'
    END AS status,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS current_lag
FROM pg_replication_slots
WHERE active = true;

3. Проверка использования диска WAL-логами:

-- Оценка, сколько WAL хранится из-за слотов
SELECT 
    slot_name,
    pg_size_pretty(
        pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)
    ) AS retained_wal,
    pg_size_pretty(
        pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) * 
        (SELECT setting::numeric FROM pg_settings WHERE name = 'wal_segment_size')
        / 16777216
    ) AS estimated_disk_usage
FROM pg_replication_slots
WHERE restart_lsn IS NOT NULL;

4. Управление слотами (административные операции):

-- Создание физического слота репликации
SELECT * FROM pg_create_physical_replication_slot('replica_slot_1');

-- Создание логического слота для логической репликации
SELECT * FROM pg_create_logical_replication_slot('logical_slot_1', 'pgoutput');

-- Принудительное продвижение restart_lsn (осторожно!)
SELECT pg_replication_slot_advance('slot_name', '0/FFFFFFF');

-- Удаление слота (только если реплика больше не нужна)
SELECT pg_drop_replication_slot('slot_name');

5. Интеграция с мониторингом (пример скрипта для Prometheus):

#!/bin/bash
# Скрипт для сбора метрик replication slots
PGHOST="localhost"
PGPORT=5432
PGDATABASE="postgres"
PGUSER="monitoring_user"

QUERY="
SELECT 
    'pg_replication_slot_lag_bytes{slot="' || slot_name || '"}' AS metric,
    pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS value
FROM pg_replication_slots
WHERE active = true AND restart_lsn IS NOT NULL
UNION ALL
SELECT 
    'pg_replication_slots_total',
    COUNT(*)::text
FROM pg_replication_slots
"

psql -h $PGHOST -p $PGPORT -U $PGUSER -d $PGDATABASE 
     -t -A -F " " -c "$QUERY" 2>/dev/null | while read metric value; do
    echo "$metric $value"
done

6. Автоматизация очистки застрявших слотов:

-- Найти неактивные слоты старше N дней
SELECT slot_name, active, xmin
FROM pg_replication_slots 
WHERE active = false 
AND (now() - pg_stat_file('pg_wal/' || 
     pg_walfile_name(restart_lsn))::timestamp) > interval '7 days';

-- Процедура для безопасного удаления старых неактивных слотов
CREATE OR REPLACE PROCEDURE cleanup_stale_replication_slots(max_age_days INT DEFAULT 7)
LANGUAGE plpgsql
AS $$
DECLARE
    slot_record RECORD;
BEGIN
    FOR slot_record IN 
        SELECT slot_name 
        FROM pg_replication_slots 
        WHERE active = false 
        AND (now() - pg_stat_file('pg_wal/' || 
             pg_walfile_name(restart_lsn))::timestamp) > 
            (max_age_days || ' days')::interval
    LOOP
        RAISE NOTICE 'Dropping stale replication slot: %', slot_record.slot_name;
        PERFORM pg_drop_replication_slot(slot_record.slot_name);
    END LOOP;
END;
$$;

-- Вызов процедуры
CALL cleanup_stale_replication_slots(7);

Критические моменты для DevOps:

  1. Мониторинг lag: Лаг больше 1GB может указывать на проблемы с сетью или производительностью реплики
  2. Дисковое пространство: Каждый незавершенный слот удерживает WAL-логи, что может заполнить диск
  3. Активность слотов: Неактивные слоты (active = false) часто указывают на проблемы с подключением реплики
  4. Резервные копии: При использовании PITR (Point-in-Time Recovery) слоты могут конфликтовать с archive_cleanup_command

Рекомендации по настройке:

  • Установите max_slot_wal_keep_size для ограничения удерживаемых WAL-логов
  • Настройте алертинг при превышении лага (например, > 100GB)
  • Регулярно проверяйте неактивные слоты и удаляйте ненужные
  • Используйте логические слоты для логической репликации только когда это действительно необходимо