Администрирование PostgreSQL, часть 4 - Конфигурирование PostgreSQL
Приветствую!

Четвёртая часть курса по PostgreSQL - разбираемся, откуда PostgreSQL берёт значения параметров, чем SET отличается от ALTER SYSTEM, и почему часть настроек применяется мгновенно, а часть - только после перезапуска 🐧.

Предисловие

В первой, второй и третьей частях мы почти не трогали настройки сервера - разве что мельком глянули shared_buffers и work_mem через SHOW. Сегодня разберёмся куда серьёзнее: откуда PostgreSQL вообще берёт значение каждого параметра, что произойдёт, если поменять его через SET, а что - через ALTER SYSTEM, и почему на один и тот же параметр эти два способа могут повлиять совершенно по-разному.

Демонстрировать снова будем на двух параллельных сессиях psql, как и в прошлом уроке про MVCC - для конфигурации это тоже отлично работает, потому что у изменений параметров есть своя область видимости, и её проще один раз увидеть, чем запомнить со слов.

Вводные данные

ПО, используемое в статье:

ПОВерсия
PostgreSQL (образ)18
psql (в образе)18
DBeaver Community26

Стенд - тот самый контейнер postgres из первой части, запущенный и доступный на 127.0.0.1:5432.

Где физически лежат настройки

BASH
cd ~/Postgres

docker compose exec postgres psql -U ivan -d raven
Нажмите, чтобы развернуть и увидеть больше

Спросим у самого сервера, где что лежит:

SQL
SHOW config_file;

SHOW hba_file;

SHOW data_directory;
Нажмите, чтобы развернуть и увидеть больше

Так как в первой части мы явно задавали PGDATA=/var/lib/postgresql/data/pgdata, data_directory и config_file будут смотреть именно туда - initdb при первом запуске контейнера сгенерировал в этом каталоге postgresql.conf, postgresql.auto.conf и pg_hba.conf со значениями по умолчанию.

Заглянуть в файлы можно прямо из хоста, не заходя в контейнер интерактивно:

BASH
docker compose exec postgres cat /var/lib/postgresql/data/pgdata/postgresql.conf | head -n 30

docker compose exec postgres cat /var/lib/postgresql/data/pgdata/postgresql.auto.conf
Нажмите, чтобы развернуть и увидеть больше

Вывод
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
Нажмите, чтобы развернуть и увидеть больше

Именно в этот файл пишет свои изменения команда ALTER SYSTEM, о которой чуть ниже.

Приоритет источников: представление pg_settings

Все параметры, их текущие значения и то, откуда они взялись, видны в одном системном представлении:

SQL
SELECT name, setting, source, context FROM pg_settings WHERE name = 'work_mem';
Нажмите, чтобы развернуть и увидеть больше

Порядок, в котором PostgreSQL ищет значение параметра, от низкого приоритета к высокому:

  1. встроенное значение по умолчанию (компилируется в сам сервер);
  2. postgresql.conf;
  3. postgresql.auto.conf (то есть ALTER SYSTEM);
  4. настройки на уровне конкретной базы данных или роли (ALTER DATABASE ... SET, ALTER ROLE ... SET);
  5. настройки текущего сеанса (SET, PGOPTIONS, параметры строки подключения).

Каждый следующий уровень перекрывает предыдущий, но только для того, кто его установил - это и есть источник всех интересных эффектов ниже.

В DBeaver то же самое представление доступно без единой строчки SQL - в свойствах подключения, вкладка Configuration, которую мы уже открывали в прошлой части: там есть поиск по имени параметра и колонка с текущим значением.

SET - изменения на уровне сессии

Откроем две сессии psql, как в прошлом уроке - без этого разница между SET и ALTER SYSTEM не так наглядна.

BASH
docker compose exec postgres psql -U ivan -d raven
Нажмите, чтобы развернуть и увидеть больше

В обеих сессиях для начала проверим значение по умолчанию:

Меняем значение только в сессии A:

SET меняет параметр только в рамках текущего подключения. Сессия B ни о чём не узнала и не узнает, пока не выполнит собственный SET.

Есть и более узкий вариант - SET LOCAL, который живёт только до конца текущей транзакции:

SQL
BEGIN;

SET LOCAL work_mem = '128MB';

SHOW work_mem; -- 128MB

COMMIT; -- или ROLLBACK

SHOW work_mem; -- снова обычное значение сессии
Нажмите, чтобы развернуть и увидеть больше

Вернуть значение к тому, что было до SET, можно командой RESET:

SQL
RESET work_mem;
Нажмите, чтобы развернуть и увидеть больше

ALTER SYSTEM - персистентные изменения

ALTER SYSTEM - это SQL-обёртка над правкой postgresql.auto.conf, доступная только суперпользователю:

SQL
ALTER SYSTEM SET work_mem = '32MB';
Нажмите, чтобы развернуть и увидеть больше

Проверим, что реально записалось на диск:

BASH
docker compose exec postgres cat /var/lib/postgresql/data/pgdata/postgresql.auto.conf
Нажмите, чтобы развернуть и увидеть больше

Но в обеих открытых сессиях SHOW work_mem; пока покажет старое значение - файл изменился, но сервер об этом ещё не знает. Нужно перечитать конфигурацию:

SQL
SELECT pg_reload_conf();
Нажмите, чтобы развернуть и увидеть больше

А теперь самое интересное - смотрим на обе сессии:

Сессия B, у которой не было собственного SET, подхватила новое значение из postgresql.auto.conf сразу после pg_reload_conf(), без переподключения. А сессия A имеет 64MB - её персональный SET перекрывает конфигурационное значение, пока она сама не сделает RESET:

Отсюда практическое правило: если параметр “не применяется” после ALTER SYSTEM + pg_reload_conf() - вероятнее всего в этой же сессии до этого выполняли ручной SET.

Убрать персистентное значение и вернуться к postgresql.conf можно так:

SQL
ALTER SYSTEM RESET work_mem;

SELECT pg_reload_conf();
Нажмите, чтобы развернуть и увидеть больше

Context: когда хватит reload, а когда нужен restart

Не все параметры одинаковы - у каждого есть context, определяющий, каким способом его вообще можно поменять:

contextЧто это значит
internalМеняется только при сборке PostgreSQL, недоступен вообще
postmasterТолько при старте сервера - нужен перезапуск
sighupПрименяется по pg_reload_conf() сразу для всех сессий
backendПодхватывается только новыми подключениями
superuser/userМожно менять на лету через SET в рамках сессии

work_mem из примера выше - как раз context = user. А вот max_connections - классический postmaster:

SQL
ALTER SYSTEM SET max_connections = 300;

SELECT pg_reload_conf();

SELECT name, setting, pending_restart FROM pg_settings WHERE name = 'max_connections';
Нажмите, чтобы развернуть и увидеть больше
Вывод
      name       | setting | pending_restart 
-----------------+---------+-----------------
 max_connections | 100     | t
Нажмите, чтобы развернуть и увидеть больше

Столбец pending_restart = t говорит: значение записано, но не применится, пока сервер не перезапустится целиком. У нас это одна команда:

BASH
systemctl --user restart postgres
Нажмите, чтобы развернуть и увидеть больше
SQL
SHOW max_connections; -- теперь 300
Нажмите, чтобы развернуть и увидеть больше

Пользовательские параметры

PostgreSQL позволяет заводить и свои собственные “переменные” - удобно, например, для передачи контекста приложения внутрь триггеров или политик RLS. Единственное требование - имя обязательно с точкой, namespace.key:

SQL
SELECT set_config('raven.tenant', 'demo', false);

SELECT current_setting('raven.tenant');
Нажмите, чтобы развернуть и увидеть больше
Вывод
 current_setting 
-----------------
 demo
Нажмите, чтобы развернуть и увидеть больше

Третий аргумент set_config - is_local: false действует до конца сессии (как обычный SET), true - только до конца транзакции (как SET LOCAL). Такие параметры точно так же можно закрепить постоянно через ALTER SYSTEM SET raven.tenant = 'demo';, если он должен быть значением по умолчанию для всего кластера.

Возможные проблемы

Забыли SELECT pg_reload_conf(); - ALTER SYSTEM только пишет файл, применяет изменения именно reload/restart.

Смотрите пункт про SET/SET LOCAL в этой же сессии выше по разговору - сессионное значение перекрывает конфигурационное, пока не будет RESET.

Если руками поправить postgresql.conf (например, при кастомном образе с примонтированным файлом) и допустить опечатку - PostgreSQL при reload просто проигнорирует некорректную строку и продолжит работать на старом значении. Проверить, что не применилось и почему, можно так:

SQL
SELECT * FROM pg_file_settings WHERE applied = false;
Нажмите, чтобы развернуть и увидеть больше

Кстати, после наших изменений количества соединений, увидим один applied = false:

Послесловие

Из этой части курса стоит уяснить одну мысль: SET - это про “здесь и сейчас, для меня”, ALTER SYSTEM - про “для всех и навсегда, но не мгновенно”.

В следующем уроке - обслуживание: VACUUM и WAL. Как раз к настройкам autovacuum_vacuum_scale_factor и checkpoint_timeout, о которых сегодня мы только слышали мельком через pg_settings, вернёмся уже предметно.

Спасибо, что читаете. Успехов в изучении PostgreSQL! 🐧

Используемые материалы

Авторские права

Автор: Иван Чёрный

Ссылка: https://r4ven.me/storage/administrirovanie-postgresql-chast-4-konfigurirovanie-postgresql/

Лицензия: CC BY-NC-SA 4.0

Использование материалов блога разрешается при условии: указания авторства/источника, некоммерческого использования и сохранения лицензии.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
↵
ESC
⌘K Горячая клавиша