Раздел 5 — PostgreSQL: установка и первоначальная настройка

Как устроен сервер баз данных и как привести его в рабочее состояние

Прогресс курса Раздел 5 из 13

Что вы освоите в этом разделе

6 академических часов: 2 часа теории, 4 часа практики. С этого раздела и до конца курса нужен локально установленный PostgreSQL 17 и pgAdmin, а также доступ к командной строке той машины, где он стоит. Онлайн-тренажёры здесь не подойдут — вы будете править файлы конфигурации и перезапускать службу.
01

Процессная архитектура PostgreSQL

PostgreSQL построен на процессах, а не на потоках. На каждое клиентское соединение операционная система создаёт отдельный процесс. Это решение объясняет и надёжность сервера, и стоимость соединения.

                        ┌─────────────────────┐
   клиент 1  ──────────▶│  backend процесс 1  │──┐
   клиент 2  ──────────▶│  backend процесс 2  │──┤
   клиент N  ──────────▶│  backend процесс N  │──┤
                        └─────────────────────┘  │
                                                 ▼
     postmaster                          ┌───────────────┐
   (главный процесс,                     │ Shared Buffers│
    принимает                            │  общая память │
    соединения)                          └───────┬───────┘
                                                 │
   фоновые процессы:                             ▼
     background writer   ──────────────▶  ┌─────────────┐
     WAL writer          ──────────────▶  │  файлы на   │
     checkpointer        ──────────────▶  │    диске    │
     autovacuum launcher ──────────────▶  └─────────────┘
     stats collector

Кто чем занят

  • postmaster — главный процесс. Слушает порт, принимает соединения, порождает backend-процессы, следит за фоновыми. Именно его запускает systemd.
  • backend — обслуживает одно клиентское соединение от начала до конца. Разбирает запрос, планирует, выполняет, отдаёт результат.
  • background writer — постепенно сбрасывает изменённые страницы из общей памяти на диск, чтобы не копить их к моменту контрольной точки.
  • WAL writer — пишет журнал предзаписи. Именно он обеспечивает букву D в ACID.
  • checkpointer — выполняет контрольные точки: гарантирует, что все изменения до определённого момента записаны на диск.
  • autovacuum launcher — запускает процессы очистки, убирающие «мёртвые» версии строк.
Почему это важно на практике. Процесс дороже потока: каждое соединение занимает несколько мегабайт памяти даже в простое. Отсюда два следствия — max_connections нельзя ставить произвольно большим, и приложению нужен пул соединений. Открывать соединение на каждый HTTP-запрос — верный способ положить сервер.

Shared Buffers — общая область памяти, через которую все процессы работают с данными. Запрос никогда не читает файл напрямую: страница сначала попадает в общий буфер, а изменения сначала пишутся в журнал (WAL), и только потом — в файлы данных. Отсюда правило: если сервер выключился внезапно, при старте PostgreSQL воспроизведёт журнал и восстановит согласованное состояние.

02

Кластер, каталог данных, база, схема

Четыре понятия, которые постоянно путают. В терминологии PostgreSQL они означают строго определённые вещи.

Иерархия

  • Экземпляр (instance) — запущенный набор процессов PostgreSQL, обслуживающий один кластер.
  • Кластер баз данных (cluster) — набор баз, управляемых одним экземпляром и лежащих в одном каталоге данных. К кластеризации в смысле отказоустойчивости отношения не имеет — термин исторический и сбивает с толку.
  • Каталог данных (PGDATA) — каталог на диске, где кластер физически живёт. Создаётся программой initdb.
  • База данных (database) — изолированный набор схем внутри кластера. Из одного соединения работать с двумя базами нельзя.
  • Схема (schema) — пространство имён внутри базы. Таблицы лежат в схемах; по умолчанию — в схеме public.
Сервер (машина)
└── Экземпляр PostgreSQL (порт 5432)
    └── Кластер = /var/lib/postgresql/17/main
        ├── База postgres      (служебная)
        ├── База template0     (эталон, не трогать)
        ├── База template1     (шаблон для новых баз)
        └── База nevabit
            ├── Схема public
            │   ├── Таблица users
            │   └── Таблица posts
            └── Схема reports
                └── Представление monthly_activity

На одной машине можно запустить несколько экземпляров — разных версий или с разными настройками. Каждый займёт свой порт и свой каталог данных. В Debian это штатный сценарий, поддержанный инструментами.

Каталог данных нельзя копировать обычным cp у работающего сервера и нельзя открывать сторонними программами. Файлы внутри — не самостоятельные документы, а часть согласованного состояния, зависящего от журнала. Для копирования есть pg_dump и pg_basebackup; о них в разделе 6.
03

Установка на Debian 13

Debian 13 (Trixie) содержит PostgreSQL 17 в основном репозитории, поэтому установка сводится к одной команде.

# Обновить список пакетов и установить сервер с клиентом
sudo apt update
sudo apt install postgresql postgresql-client

# Проверить, что установилось
psql --version
# psql (PostgreSQL) 17.x

Если нужна версия новее той, что в дистрибутиве, подключают официальный репозиторий проекта — PGDG:

# Репозиторий PostgreSQL Global Development Group
sudo apt install curl ca-certificates
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
     --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc

echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
https://apt.postgresql.org/pub/repos/apt trixie-pgdg main" \
  | sudo tee /etc/apt/sources.list.d/pgdg.list

sudo apt update
sudo apt install postgresql-17
Пакет из основного репозитория Debian получает обновления безопасности вместе с системой и совместим с unattended-upgrades. PGDG нужен только тогда, когда требуется версия, которой в дистрибутиве ещё нет. Для учебных и большинства рабочих задач достаточно штатного пакета.

Что установка сделала с системой:

Результат установки

  • Создан системный пользователь postgres — от его имени работают все процессы сервера.
  • Выполнен initdb и создан кластер с именем main.
  • Кластер запущен и добавлен в автозагрузку через systemd.
  • Создана база postgres и роль суперпользователя postgres.
  • Сервер слушает localhost:5432 — снаружи недоступен.

Debian раскладывает файлы иначе, чем это делает initdb по умолчанию: конфигурация отделена от данных.

ПутьЧто там
/etc/postgresql/17/main/postgresql.conf, pg_hba.conf, pg_ident.conf
/var/lib/postgresql/17/main/каталог данных: файлы таблиц, WAL, служебные каталоги
/var/log/postgresql/журналы сервера
/usr/lib/postgresql/17/bin/исполняемые файлы: postgres, initdb, pg_dump
/var/run/postgresql/сокет и pid-файл
В сборках от PGDG и в официальном Docker-образе раскладка другая: конфигурация лежит внутри каталога данных, как задумано разработчиками PostgreSQL. Поэтому инструкции из интернета часто не совпадают с тем, что вы видите на Debian. Проверять расположение нужно запросом SHOW config_file;, а не поиском по диску.
04

Управление кластером

В Debian есть свой слой управления кластерами — пакет postgresql-common. Он позволяет держать несколько версий и несколько кластеров одновременно.

# Список всех кластеров на машине
pg_lsclusters
# Ver Cluster Port Status Owner    Data directory              Log file
# 17  main    5432 online postgres /var/lib/postgresql/17/main /var/log/...

# Управление конкретным кластером: версия, имя, действие
sudo pg_ctlcluster 17 main start
sudo pg_ctlcluster 17 main stop
sudo pg_ctlcluster 17 main restart
sudo pg_ctlcluster 17 main reload    # перечитать конфигурацию без разрыва соединений

# Создать второй кластер на другом порту
sudo pg_createcluster 17 test --port=5433 --start

Параллельно работает обычное управление через systemd:

sudo systemctl status postgresql@17-main
sudo systemctl restart postgresql@17-main
sudo systemctl enable postgresql@17-main    # автозапуск

# postgresql.service — это обёртка, управляющая всеми кластерами сразу
sudo systemctl restart postgresql
Разница между restart и reload существенна. reload заставляет сервер перечитать конфигурацию, не разрывая соединений и не прерывая работу приложения. restart обрывает все соединения. На рабочем сервере всегда сначала пробуйте reload — большинство параметров этого достаточно.

Если сервер не поднимается — смотреть нужно журнал, а не гадать:

sudo tail -n 50 /var/log/postgresql/postgresql-17-main.log
sudo journalctl -u postgresql@17-main -n 50 --no-pager
05

postgresql.conf: параметры сервера

Основной файл конфигурации. Формат простой: параметр = значение, комментарии после #.

Параметры, которые настраивают в первую очередь

  • listen_addresses — на каких адресах слушать. 'localhost' по умолчанию, '*' — на всех интерфейсах.
  • port — порт, по умолчанию 5432.
  • max_connections — предел одновременных соединений. Каждое стоит памяти.
  • shared_buffers — размер общего буферного кэша. Ориентир — 25% ОЗУ.
  • effective_cache_size — подсказка планировщику, сколько памяти суммарно доступно под кэш (включая кэш ОС). Память не выделяет, влияет только на выбор плана. Ориентир — 50–75% ОЗУ.
  • work_mem — память на одну операцию сортировки или хеширования. Выделяется на операцию, а не на соединение: сложный запрос может занять несколько порций.
  • maintenance_work_mem — память под VACUUM, CREATE INDEX, ALTER TABLE.
  • wal_level — объём информации в журнале: replica по умолчанию, logical для логической репликации.
  • log_min_duration_statement — писать в журнал запросы дольше указанного времени в миллисекундах. Главный инструмент поиска медленных запросов.
  • password_encryptionscram-sha-256 начиная с PostgreSQL 14.

Контексты применения

Не всякий параметр можно изменить на лету. У каждого есть контекст, определяющий, что нужно сделать для вступления изменений в силу.

КонтекстЧто требуетсяПримеры
postmasterперезапуск сервераshared_buffers, max_connections, listen_addresses, port
sighupreloadlog_min_duration_statement, autovacuum
superuserизменение в сессии суперпользователемlog_statement
userизменение в своей сессии любым пользователемwork_mem, search_path
internalзадаётся при сборке или initdb, изменить нельзяblock_size, lc_collate
-- Узнать текущее значение и контекст параметра
SHOW shared_buffers;

SELECT name, setting, unit, context, source
FROM   pg_settings
WHERE  name IN ('shared_buffers', 'work_mem', 'max_connections');

-- Какие параметры изменены относительно умолчаний
SELECT name, setting, source
FROM   pg_settings
WHERE  source NOT IN ('default', 'override');

-- Где лежат файлы конфигурации
SHOW config_file;
SHOW hba_file;
SHOW data_directory;

Три способа задать параметр

Способы и приоритет

  • Правка postgresql.conf — базовый способ, файл под контролем администратора и системы конфигурации.
  • Файлы в conf.d/ — если в основном файле есть include_dir 'conf.d'. Удобно: свои настройки лежат отдельно от дистрибутивных и переживают обновление пакета.
  • ALTER SYSTEM — команда SQL, пишет в postgresql.auto.conf. Этот файл читается последним и перекрывает всё остальное.
-- Изменить параметр из SQL
ALTER SYSTEM SET log_min_duration_statement = '500ms';
SELECT pg_reload_conf();

-- Отменить своё изменение и вернуться к значению из postgresql.conf
ALTER SYSTEM RESET log_min_duration_statement;
SELECT pg_reload_conf();
Классическая потеря времени: администратор правит postgresql.conf, перезапускает сервер, а значение не меняется — потому что тот же параметр когда-то задали через ALTER SYSTEM, и он лежит в postgresql.auto.conf. Столбец source в pg_settings сразу показывает, откуда взято действующее значение. Проверяйте его первым делом.
06

pg_hba.conf: кто и как подключается

HBA расшифровывается как Host-Based Authentication. Этот файл решает, кому разрешено подключаться и каким способом он должен доказать, что он — это он.

Формат строки — пять или шесть полей:

# ТИП    БАЗА     ПОЛЬЗОВАТЕЛЬ  АДРЕС            МЕТОД

local    all      postgres                       peer
local    all      all                            peer
host     all      all           127.0.0.1/32     scram-sha-256
host     all      all           ::1/128          scram-sha-256
host     nevabit  nevabit_app   10.0.0.0/24      scram-sha-256
hostssl  nevabit  nevabit_app   0.0.0.0/0        scram-sha-256
host     all      all           0.0.0.0/0        reject

Поля

  • ТИП: local — через Unix-сокет; host — по TCP с шифрованием или без; hostssl — только с TLS; hostnossl — только без TLS.
  • БАЗА: имя базы, список через запятую или all.
  • ПОЛЬЗОВАТЕЛЬ: имя роли, +имя_группы или all.
  • АДРЕС: адрес или подсеть в формате CIDR. Для local не указывается.
  • МЕТОД: способ проверки подлинности.
МетодКак проверяетКогда применять
scram-sha-256пароль по протоколу SCRAMосновной метод для сетевых подключений
peerимя системного пользователя ОСлокальные подключения через сокет
identвнешняя служба identпрактически не используется
md5устаревшее хеширование паролятолько для старых клиентов
certклиентский TLS-сертификатсервис-сервис без паролей
trustпускает без проверкиникогда вне изолированного стенда
rejectотказывает всегдаявный запрет в конце файла
Правила читаются сверху вниз, побеждает первое подходящее. Если оно отказало — подключение отклоняется, до следующих строк дело не доходит. Отсюда две ошибки: разрешающее правило поставили ниже запрещающего, или широкое правило all all перекрыло узкое. Порядок строк здесь — часть логики, а не оформление.

Метод peer объясняет, почему сразу после установки работает такая команда:

# Переключиться на системного пользователя postgres и войти в psql
sudo -u postgres psql

Пароль не спрашивается: PostgreSQL спрашивает у ядра, от чьего имени пришло соединение через сокет, видит системного пользователя postgres и пускает его в роль с тем же именем.

После правки pg_hba.conf достаточно reload — перезапуск не нужен. Проверить, какое правило сработало для действующих соединений, можно запросом к pg_hba_file_rules: он же покажет строки с синтаксическими ошибками до того, как вы их примените.
-- Проверить файл на ошибки, не перезагружая конфигурацию
SELECT line_number, type, database, user_name, address, auth_method, error
FROM   pg_hba_file_rules
WHERE  error IS NOT NULL;
07

Первое подключение и psql

psql — штатный клиент командной строки. Он не только выполняет SQL, но и умеет исследовать структуру базы метакомандами, начинающимися с обратной косой черты.

# Подключение: пользователь, база, хост, порт
psql -U nevabit_app -d nevabit -h localhost -p 5432

# Строка подключения одним аргументом
psql "postgresql://nevabit_app@localhost:5432/nevabit"

# Выполнить один запрос и выйти
psql -U postgres -c "SELECT version();"

# Выполнить файл
psql -U nevabit_app -d nevabit -f socialnet_db.sql

Метакоманды, которые нужны сразу

  • \l — список баз данных
  • \c имя_базы — переключиться на другую базу
  • \dt — таблицы текущей схемы
  • \d имя_таблицы — структура таблицы: столбцы, типы, индексы, ограничения
  • \d+ имя_таблицы — то же плюс размер и описания
  • \du — список ролей и их атрибутов
  • \dn — список схем
  • \di — индексы
  • \x — расширенный вывод: строки печатаются по вертикали, спасает на широких таблицах
  • \timing — показывать время выполнения каждого запроса
  • \e — открыть текущий запрос в редакторе
  • \i файл.sql — выполнить файл
  • \conninfo — параметры текущего соединения
  • \? — справка по метакомандам, \h SELECT — справка по синтаксису команды
  • \q — выход

Создание рабочей базы и пользователя приложения — минимальный сценарий после установки:

-- От имени postgres
CREATE ROLE nevabit_app LOGIN PASSWORD 'смените_этот_пароль';
CREATE DATABASE nevabit OWNER nevabit_app ENCODING 'UTF8';

-- Проверка
\l
\du
Кодировка и правила сортировки задаются при создании базы и не меняются потом — только пересозданием с переносом данных. Для русского языка правильный выбор — ENCODING 'UTF8' и локаль ru_RU.UTF-8. Если создать базу с локалью C, сортировка русского текста пойдёт по кодам символов: «Ёж» окажется после «Яблока».
08

Настройка под сервер с малыми ресурсами

Значения по умолчанию у PostgreSQL намеренно скромные — они рассчитаны на то, чтобы сервер запустился где угодно. На типичном VPS их нужно поднимать; на очень маленьком — следить, чтобы сервер не съел всю память.

Пример расчёта для машины 1 CPU / 1 ГБ ОЗУ — распространённая конфигурация недорогого VPS:

ПараметрПо умолчаниюДля 1 ГБОбоснование
shared_buffers128MB256MB25% ОЗУ
effective_cache_size4GB512MBподсказка планировщику, память не занимает
work_mem4MB4MBумножается на число операций — повышать опасно
maintenance_work_mem64MB64MBразово при VACUUM и построении индексов
max_connections10040остальное закрывается пулом соединений
max_worker_processes82одно ядро
max_parallel_workers_per_gather20параллелизм на одном ядре только вредит
Самая частая ошибка на маленьком сервере — задрать work_mem. Параметр выделяется на каждую операцию сортировки или хеширования в каждом запросе. При work_mem = 64MB, сорока соединениях и трёх сортировках на запрос теоретический предел — почти 8 ГБ. Сервер уйдёт в swap или будет убит OOM-killer'ом.

Настройки уровня операционной системы, без которых маленький сервер живёт хуже:

# Swap обязателен даже при быстром диске — как страховка от OOM
# Но обращаться к нему система должна неохотно
sudo sysctl -w vm.swappiness=10
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf

# Посмотреть, сколько памяти реально занято
free -h
ps -o pid,rss,cmd -C postgres
Пул соединений на маленьком сервере важнее любой настройки памяти. PgBouncer в режиме transaction позволяет сотне клиентов приложения работать через десяток реальных соединений к базе. Это дешевле, чем увеличивать max_connections, и почти всегда быстрее.
09

Безопасность первичной настройки

Свежеустановленный PostgreSQL закрыт разумно, но первые же шаги по «настройке доступа» обычно эту защиту снимают.

Что проверить сразу

  • Не открывайте listen_addresses = '*' без необходимости. Если приложение на той же машине — оставьте localhost. Порт 5432, открытый в интернет, сканируется в первые же часы.
  • Никакого trust для сетевых подключений. Метод trust пускает вообще без проверки. Единственное его законное применение — восстановление доступа, когда забыт пароль суперпользователя, и то временно.
  • Приложение работает не суперпользователем. Роль nevabit_app с правами только на свою базу; о разграничении прав — раздел 6.
  • Пароли — только scram-sha-256. Проверьте password_encryption и убедитесь, что в pg_hba.conf нет md5.
  • Файрвол. ufw с разрешёнными 22, 80 и 443; порт базы наружу не выставляется.
  • TLS для внешних подключений. Если база всё же доступна по сети — hostssl вместо host, чтобы незашифрованное соединение просто не устанавливалось.
  • Пароль суперпользователя postgres. После установки его нет: роль доступна только через peer. Задавать пароль стоит лишь тогда, когда он действительно нужен.
# Проверить, что снаружи порт закрыт
sudo ss -tlnp | grep 5432
# LISTEN 127.0.0.1:5432 — хорошо
# LISTEN 0.0.0.0:5432   — открыт на всех интерфейсах, проверьте файрвол

sudo ufw status
Совет «поставьте host all all 0.0.0.0/0 trust, чтобы заработало» встречается в интернете постоянно и означает: любой, кто дотянулся до порта, получает права суперпользователя базы. Если подключение не работает — читайте журнал сервера, там написана точная причина отказа и номер сработавшей строки pg_hba.conf.

Ключевые выводы раздела

Запомните главное

  • PostgreSQL — процессная архитектура: соединение стоит памяти, поэтому нужен пул
  • Кластер — набор баз в одном каталоге данных под одним экземпляром, к отказоустойчивости отношения не имеет
  • В Debian конфигурация в /etc/postgresql/17/main/, данные в /var/lib/postgresql/17/main/; в Docker и PGDG — иначе
  • Расположение файлов узнаётся запросом SHOW config_file, а не поиском по диску
  • reload перечитывает конфигурацию без разрыва соединений; restart обрывает все
  • У параметра есть контекст: часть требует перезапуска, часть — только reload
  • ALTER SYSTEM пишет в postgresql.auto.conf и перекрывает postgresql.conf; источник виден в pg_settings.source
  • В pg_hba.conf побеждает первое подходящее правило — порядок строк является логикой
  • work_mem выделяется на каждую операцию, а не на соединение
  • Кодировка и локаль базы задаются при создании и потом не меняются
Практические задания — на учебном портале. Задания, критерии оценивания, сдача работ и оценки преподавателя — в курсе на portal.nevabit.ru. Учётную запись выдаёт преподаватель.
Раздел 4: Нормализация Раздел 6: Администрирование