Администрирование
Администрирование PostgreSQL¶
Установить PostgreSQL — 5 минут. Настроить для продакшена — совсем другая история. В этой статье разберём ключевые аспекты администрирования: конфигурацию, безопасность, обслуживание и мониторинг.
postgresql.conf — главный конфиг¶
Файл postgresql.conf определяет поведение сервера. Большинство параметров можно изменить без перезагрузки (SELECT pg_reload_conf()), но некоторые требуют рестарта.
Память¶
# Общий буферный кеш — основной кеш данных в RAM
# Рекомендация: 25% от RAM (но не больше 8-16 GB на SSD)
shared_buffers = 4GB
# Рабочая память для одного запроса (сортировка, hash join)
# Осторожно: умножается на количество одновременных операций!
# 100 сессий × 256MB = 25GB
work_mem = 256MB
# Память для обслуживающих операций (VACUUM, CREATE INDEX)
maintenance_work_mem = 1GB
# Кеш, управляемый ОС — подсказка планировщику
# Рекомендация: 75% от RAM
effective_cache_size = 12GB
work_mem — самый опасный параметр
work_mem выделяется на каждую операцию сортировки/хеширования, а их может быть несколько в одном запросе. При 200 подключениях и work_mem = 512MB сервер может съесть 100 GB RAM. Начинай с 64-128 MB, увеличивай для конкретных сессий через SET work_mem = '512MB'.
Запись и WAL¶
# Синхронная запись WAL — безопасность vs скорость
synchronous_commit = on # on = безопасно, off = быстрее, риск потери <0.5s
# Размер WAL-сегмента
wal_buffers = 64MB
# Checkpoints — как часто данные из WAL сбрасываются на диск
checkpoint_timeout = 15min # дефолт 5min, можно увеличить для write-heavy
max_wal_size = 4GB # Макс WAL между чекпоинтами
min_wal_size = 1GB
Подключения¶
Параметры, требующие рестарта¶
| Параметр | Что делает | Рестарт? |
|---|---|---|
shared_buffers |
Размер буферного кеша | Да |
max_connections |
Лимит подключений | Да |
wal_level |
Уровень WAL (minimal/replica/logical) | Да |
work_mem |
Память на операцию | Нет (reload) |
random_page_cost |
Оценка стоимости случайного чтения | Нет (reload) |
effective_cache_size |
Подсказка планировщику | Нет (reload) |
-- Применить изменения без рестарта
SELECT pg_reload_conf();
-- Проверить текущее значение
SHOW shared_buffers;
SHOW work_mem;
-- Временно для текущей сессии
SET work_mem = '512MB';
pg_hba.conf — контроль доступа¶
Файл pg_hba.conf определяет кто, откуда и как может подключиться. PostgreSQL проверяет правила сверху вниз — первое совпадение побеждает.
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
host all all 127.0.0.1/32 scram-sha-256
host etl_db etl_user 10.0.0.0/24 scram-sha-256
host all all 0.0.0.0/0 reject
| Метод | Описание | Когда использовать |
|---|---|---|
peer |
ОС-аутентификация (Linux user = PG user) | Локальные подключения |
scram-sha-256 |
Пароль с хешированием (безопасный) | Удалённые подключения |
md5 |
Пароль с MD5 (устаревший) | Legacy-совместимость |
reject |
Отклонить | Явный запрет |
cert |
Клиентский SSL-сертификат | Продакшн с высокой безопасностью |
Никогда не используй trust
trust пропускает любого без пароля. Допустимо только для локальной разработки в изолированном контейнере.
Роли и привилегии¶
PostgreSQL использует роли (roles) вместо понятий «пользователь» и «группа». Роль может иметь атрибут LOGIN (тогда это пользователь) или не иметь (тогда это групповая роль).
Создание ролей¶
-- Пользователь для приложения (минимальные права)
CREATE ROLE app_user LOGIN PASSWORD 'strong_password';
-- Групповая роль для аналитиков
CREATE ROLE analytics NOLOGIN;
-- Назначить групповую роль пользователю
GRANT analytics TO data_engineer;
Принцип наименьших привилегий¶
-- Отозвать все права по умолчанию
REVOKE ALL ON DATABASE etl_db FROM PUBLIC;
REVOKE ALL ON SCHEMA public FROM PUBLIC;
-- Приложению — только CRUD
GRANT CONNECT ON DATABASE etl_db TO app_user;
GRANT USAGE ON SCHEMA public TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_user;
-- Аналитикам — только чтение
GRANT CONNECT ON DATABASE etl_db TO analytics;
GRANT USAGE ON SCHEMA public TO analytics;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO analytics;
-- Для будущих таблиц
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO analytics;
Аудит ролей¶
-- Кто имеет доступ к таблице?
SELECT grantee, privilege_type
FROM information_schema.table_privileges
WHERE table_name = 'customers';
-- Все роли и их атрибуты
SELECT rolname, rolsuper, rolcreatedb, rolcanlogin
FROM pg_roles
ORDER BY rolname;
VACUUM — обслуживание таблиц¶
PostgreSQL использует MVCC (Multi-Version Concurrency Control): при UPDATE создаётся новая версия строки, старая помечается как «мёртвая» (dead tuple). VACUUM очищает мёртвые строки и обновляет статистику.
Виды VACUUM¶
-- Обычный VACUUM — освобождает место для переиспользования (не уменьшает файл)
VACUUM orders;
-- VACUUM ANALYZE — VACUUM + обновление статистики для планировщика
VACUUM ANALYZE orders;
-- VACUUM FULL — полная перезапись таблицы (уменьшает файл, но блокирует таблицу!)
VACUUM FULL orders;
| Вид | Блокировка | Уменьшает файл | Скорость | Когда |
|---|---|---|---|---|
VACUUM |
Нет (concurrent) | Нет | Быстро | Автоматически (autovacuum) |
VACUUM FULL |
Exclusive lock! | Да | Медленно | Крайне редко, при критическом bloat |
VACUUM ANALYZE |
Нет | Нет | Быстро | После массовых INSERT/UPDATE |
Autovacuum¶
Autovacuum запускается автоматически и обычно достаточно. Но для больших таблиц может отставать.
-- Текущие autovacuum-процессы
SELECT pid, datname, relid::regclass, phase, heap_blks_scanned, heap_blks_total
FROM pg_stat_progress_vacuum;
-- Когда был последний vacuum?
SELECT relname, last_vacuum, last_autovacuum, n_dead_tup, n_live_tup
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;
-- Настройка autovacuum для конкретной таблицы
ALTER TABLE events SET (
autovacuum_vacuum_threshold = 1000,
autovacuum_vacuum_scale_factor = 0.05, -- запускать при 5% мёртвых (дефолт 20%)
autovacuum_analyze_threshold = 500
);
Формула запуска autovacuum
Autovacuum запускается когда: dead_tuples > threshold + scale_factor × n_live_tup. По умолчанию: 50 + 0.2 × n_live_tup. Для таблицы в 10 млн строк это 2 млн мёртвых строк — может быть слишком поздно.
Transaction ID Wraparound¶
PostgreSQL использует 32-битные transaction ID (XID). При ~2 млрд транзакций ID «оборачивается» и все данные становятся «из будущего» → база встаёт. Autovacuum предотвращает это через FREEZE.
-- Проверить возраст XID
SELECT datname, age(datfrozenxid), datfrozenxid
FROM pg_database
ORDER BY age(datfrozenxid) DESC;
-- Опасно если age > 200_000_000
-- Критично если age > 1_000_000_000
Мониторинг¶
Ключевые представления¶
-- Активные запросы
SELECT pid, usename, state, query_start,
now() - query_start AS duration,
LEFT(query, 80) AS query
FROM pg_stat_activity
WHERE state = 'active' AND pid != pg_backend_pid()
ORDER BY duration DESC;
-- Размер таблиц и индексов
SELECT relname,
pg_size_pretty(pg_total_relation_size(relid)) AS total,
pg_size_pretty(pg_relation_size(relid)) AS table_only,
pg_size_pretty(pg_indexes_size(relid)) AS indexes
FROM pg_stat_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 10;
-- Кеш-хит rate (должен быть > 99%)
SELECT datname,
blks_hit::float / NULLIF(blks_hit + blks_read, 0) * 100 AS cache_hit_pct
FROM pg_stat_database
WHERE datname = current_database();
pg_stat_statements¶
Расширение для анализа производительности запросов — must-have для продакшена.
-- Включить
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- postgresql.conf: shared_preload_libraries = 'pg_stat_statements'
-- Самые медленные запросы
SELECT LEFT(query, 80) AS query,
calls,
round(total_exec_time::numeric / 1000, 2) AS total_sec,
round(mean_exec_time::numeric, 2) AS avg_ms,
rows
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
Блокировки¶
-- Текущие блокировки
SELECT blocked.pid AS blocked_pid,
blocked.query AS blocked_query,
blocking.pid AS blocking_pid,
blocking.query AS blocking_query
FROM pg_stat_activity blocked
JOIN pg_locks bl ON bl.pid = blocked.pid
JOIN pg_locks lock ON lock.locktype = bl.locktype
AND lock.relation = bl.relation
AND lock.pid != bl.pid
JOIN pg_stat_activity blocking ON blocking.pid = lock.pid
WHERE NOT bl.granted;
PgBouncer — пул подключений¶
PostgreSQL создаёт отдельный процесс на каждое подключение (~5-10 MB RAM). При 500+ подключениях сервер тратит ресурсы на управление процессами вместо запросов.
PgBouncer — лёгкий прокси (~2 KB на подключение), который управляет пулом.
Режимы¶
| Режим | Описание | Для кого |
|---|---|---|
session |
Подключение к PG живёт всю сессию клиента | Legacy-приложения, prepared statements |
transaction |
Подключение возвращается в пул после каждой транзакции | Большинство приложений — рекомендуется |
statement |
Возврат после каждого SQL-запроса | Простые read-only нагрузки |
Конфигурация¶
# pgbouncer.ini
[databases]
etl_db = host=127.0.0.1 port=5432 dbname=etl_kitchen
[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
default_pool_size = 20 # подключений к PG на БД
max_client_conn = 1000 # клиентских подключений
min_pool_size = 5
reserve_pool_size = 5
Мониторинг PgBouncer¶
-- Подключиться к PgBouncer admin
-- psql -p 6432 pgbouncer
SHOW POOLS; -- состояние пулов
SHOW CLIENTS; -- клиентские подключения
SHOW STATS; -- статистика
PostgreSQL 14+ и встроенный пулинг
pg_prewarm и параметр max_connections + reserved_connections в PostgreSQL 17 упрощают ситуацию, но PgBouncer всё ещё лучше для >200 подключений.
Бэкапы¶
pg_dump — логический бэкап¶
# Полный дамп базы в custom-формат (сжатый, параллельный восстановление)
pg_dump -Fc -j4 -d etl_kitchen -f etl_kitchen.dump
# Только структура
pg_dump -s -d etl_kitchen -f schema.sql
# Только данные конкретной таблицы
pg_dump -t orders --data-only -d etl_kitchen -f orders_data.sql
# Восстановление
pg_restore -d etl_kitchen -j4 etl_kitchen.dump
pg_basebackup — физический бэкап¶
# Полная копия кластера (для PITR)
pg_basebackup -D /backup/base -Ft -z -P -X stream
# С WAL-архивированием для Point-in-Time Recovery
| Метод | Скорость | PITR | Гранулярность | Размер |
|---|---|---|---|---|
pg_dump |
Медленнее | Нет | Таблица/БД | Меньше (только данные) |
pg_basebackup |
Быстрее | Да | Весь кластер | Больше (полная копия) |
Попробуй сам¶
Посмотри статистику текущей базы данных.
Проверь себя¶
Источники¶
- PostgreSQL: Server Configuration — все параметры postgresql.conf
- PostgreSQL: Client Authentication — pg_hba.conf и методы аутентификации
- PostgreSQL: Routine Vacuuming — VACUUM, autovacuum, XID wraparound
- PostgreSQL: Monitoring — pg_stat_activity, pg_stat_statements
- PgBouncer: Documentation — конфигурация пулера подключений