Архиватор запускается только после завершения сегмента WAL. В загруженной базе данных это происходит постоянно, а в малоактивной — может не происходить часами или даже днями. Параметр archive_timeout предназначен для того, чтобы избежать ситуации вроде «наша база данных весь день принимала операции записи, но ни одна из них ещё не попала в архив».
archive_mode — это главный выключатель архивации WAL. После трёх предыдущих статей — archive_cleanup_command, archive_command, archive_library — мы наконец добрались до параметра, который решает, будет ли вообще работать вся эта механика.
Прежде чем погрузиться в этот параметр, небольшое исправление (errata) к предыдущей статье. Я сказал, что инструменты резервного копирования «могут зарегистрироваться как archive_library и полностью обойти archive_command» начиная с PostgreSQL 15+. Именно для этого и была предназначена эта функциональность. Однако это не то, что на самом деле появилось в экосистеме. Подробнее об этом чуть позже.
archive_library, добавленный в PostgreSQL 15, позволяет настроить загружаемый C-модуль для обработки архивации WAL вместо команды оболочки (shell command). Процесс архиватора (archiver process) вызывает колбэки модуля напрямую, внутри своего процесса, один раз на каждый сегмент. Никакого fork(). Никакой оболочки. Никакого cp. PostgreSQL передаёт завершённые WAL-файлы модулю и не будет переиспользовать их, пока модуль не подтвердит успех, — контракт тот же, что и у archive_command, но без накладных расходов и режимов отказа, присущих сценариям оболочки.
Алфавитный порядок выдал нам первую «жертву». archive_cleanup_command — это параметр резервного сервера (standby-server knob), который существует исключительно для того, чтобы прибираться после archive_command. Однако алфавит настаивает на том, чтобы отложить рассмотрение archive_command до следующей статьи. Поэтому мы опишем, как прибирать вечеринку, которую ещё не устраивали.
Кратчайшая предыстория: Первичный сервер PostgreSQL (primary) может архивировать свои сегменты WAL в некоторое место — каталог, корзину S3, общий ресурс NFS — выполняя команду оболочки для каждого заполненного сегмента. Резервные серверы (standbys) читают из этого места, чтобы догонять изменения, а инструменты резервного копирования читают из него для обеспечения восстановления на момент времени (point-in-time recovery, PITR). Файлы накапливаются. Кто-то должен их удалять.
Для хорошего бэкенд-разработчика существует определенное стремление к оптимизации запросов (скорости и памяти). Одним из полезных инструментов оптимизации баз данных являются подзапросы SQL.
Подзапрос - это запрос внутри другого запроса. Он позволяет вам вытащить связанные данные или результаты вычислений без написания нескольких запросов или тяжелых соединений. Он также позволяет динамически выполнять вычисления и агрегировать данные.
Большинство GUC в этой серии будут операционно не важны для большинства читателей. Этот — не такой. application_name — это самое дешёвое средство наблюдаемости (observability infrastructure), которое поставляет PostgreSQL, и поразительное количество производственных баз данных работают с неустановленным значением или со значением, застрявшим на значении по умолчанию клиентской библиотеки (psql, PostgreSQL JDBC Driver или, что я люблю больше всего, — пустая строка).
Это метка уровня сеанса (per-session label). Значение по умолчанию — пустая строка, контекст — user, поэтому любая роль может его установить. Установите его через SET application_name = 'order-service';, через параметр подключения application_name или через переменную окружения PGAPPNAME, которую libpq учитывает автоматически. Максимальная длина — NAMEDATALEN - 1 — 63 байта в стандартной сборке, а непечатаемые символы заменяются на ?.
Вот GUC, который поставляется с предупреждающей этикеткой. Документация, обычно сдержанная до степени пародии, прямо заявляет, что неправильная установка этого параметра может привести к «необратимой потере данных или серьёзному повреждению системы базы данных». Когда документация PostgreSQL так повышает голос — прислушайтесь.
Давайте начнем с базы данных Stack Overflow (будет работать версия любого размера), удалим все индексы на таблице Users и выполним DELETE:
SET STATISTICS IO ON;
GO
BEGIN TRAN
DELETE dbo.Users WHERE DisplayName = N'Brent Ozar';
Я использую SET STATISTICS IO ON, о чем мы говорили в статье "Как думать подобно серверу SQL Server" для иллюстрации количества прочитанных данных, и я делаю это в транзакции, которую я могу периодически откатывать, каждый раз демонстрируя полученные эффекты. Вот действительный план выполнения:
allow_in_place_tablespaces существует для того, чтобы набор тестов PostgreSQL мог тестировать репликацию. Вот и всё. Если вы читаете это как администратор (оператор), вы никогда к нему не прикоснётесь. Но раз он есть в алфавите, вот мы здесь.
GUC — это аббревиатура от Grand Unified Configuration (Великая унифицированная конфигурация).
В контексте PostgreSQL это просто техническое название для всех параметров (настроек) сервера, которые можно менять.
Простыми словами, это переменные, которые определяют, как работает ваш экземпляр PostgreSQL.
Мы начинаем с allow_alter_system — параметра, который одновременно и новый, и политически взрывоопасный. Поэтому давайте начнём со спора.
Команда ALTER SYSTEM была добавлена в PostgreSQL 9.4 как улучшение качества жизни: возможность устанавливать GUC (Grand Unified Configuration — унифицированные параметры конфигурации) из SQL-приглашения, записывая значения в postgresql.auto.conf, без необходимости доступа к оболочке операционной системы. Однако она сразу же вызвала споры среди тех, кто управляет PostgreSQL с помощью систем управления конфигурацией. Если Ansible управляет postgresql.conf, но суперпользователь незаметно выполняет ALTER SYSTEM SET work_mem = '1GB', следующий запуск Ansible не трогает postgresql.auto.conf, и расхождение (дрейф) конфигурации сохраняется бесконечно. Никто не замечает проблемы, пока что-то не сломается.
Этот спор занял примерно десятилетие. В PostgreSQL 17 появился параметр allow_alter_system — булевый параметр, который, когда установлен в off, заставляет ALTER SYSTEM возвращать ошибку: ERROR: ALTER SYSTEM is not allowed in this environment. Значение по умолчанию — on, контекст — sighup, так что для его изменения требуется лишь перезагрузка конфигурации.
Каждый администратор баз данных держит в голове инструментарий готовых запросов. Некоторым потребовались годы, чтобы научиться. Некоторые были случайно обнаружены во время работы в 2 часа ночи. Сегодня я поделюсь 10-ю моими самыми любимыми короткими запросами T-SQL, теми, что копируешь, вставляешь и сразу чувствуешь себя гением. Некоторые из них - классические, некоторые - из недавнего пополнения, и все из них полезны. Ставьте закладку, я надеюсь, что вы сюда вернетесь.
1. Генерация числовой последовательности на лету
Нужно быстро получить последовательность чисел без создания таблицы подсчета? Если вы имеете SQL Server 2022 или более позднюю версию, GENERATE_SERIES - ваш новый лучший друг:
SELECT value FROM GENERATE_SERIES(1, 100);
Это все. Одна строка кода. 100 строк в последовательности. Никаких временных таблиц, никаких CTE, никаких перекрестных соединений. Аналогичный прием для диапазона дат. Используйте это для получения каждого дня 2025 года в одной строке:
SELECT DATEADD(DAY, value, '2025-01-01') AS dt FROM GENERATE_SERIES(0, 364);
Предыдущая статья о регрессии производительности pgbench на Linux 7.0 заканчивалась тем же указанием, которым заканчивается любая другая статья о производительности Postgres: включите huge pages. Эта статья — подробная версия. Если вы читали документацию Postgres о huge_pages, но всё ещё не совсем уверены, что вам говорит /proc/meminfo, какова связь между vm.nr_hugepages и Transparent Huge Pages, или почему huge_pages = try — неправильный выбор, то эта статья для вас.
Здесь не так много нового материала. Однако есть материал, о который люди продолжают спотыкаться, несмотря на то, что он описан в документации.