В дни майского HighLoad++ Foundation 2022 наша компания объявила о выпуске Postgres Pro Enterprise 14.2.1. С тех пор вышло несколько обновлений, мы расскажем о наиболее свежем из них - Postgres Pro Enterprise 14.4.1, основанном на PostgreSQL 14.4. Этот выпуск включает все новые возможности, появившиеся в «ванильной» PostgreSQL 14, а также исправления ошибок, вошедшие в недавние корректирующие выпуски PostgreSQL. В данной статье специалисты Postgres Professional решили обобщить ключевые возможности Postgres Pro Enterprise 14.4.1.
Обновлённый модуль pgpro_pwr
О модуле для детального анализа исторической нагрузки pgpro_pwr мы неоднократно рассказывали на PGConf.Russia и в различных статьях. В новом выпуске Postgres Pro Enterprise pgpro_pwr обновлён до версии 3.9, и теперь в отчёт включается статистика по событиям аннулирования и очистке таблиц и индексов. Документацию для свежего pgpro_pwr можно почитать здесь.
Кстати, разработчик модуля Андрей Зубков сделал доклад о его использовании для анализа того, чем занимался VACUUM, на нашей недавней конференции.
Cбор статистики VACUUM для таблиц и индексов
В расширении pgpro_stats, которым пользуется pgpro_pwr, теперь реализован и сбор статистики очистки таблиц и индексов. В новых представлениях pgpro_stats_vacuum_indexes и pgpro_stats_vacuum_tables доступны детализированные сведения об очистке таблиц и индексов (в том числе для TOAST). Какая конкретно информация собирается, можно почитать в документации модуля.
Кроме того, в обновлённый модуль pgpro_stats 1.4 добавлены одноимённые функции, которые определяют эти представления для любой указанной базы данных и таблицы/индекса, а также могут возвращать статистику очистки всех таблиц/индексов в указанной базе данных.
Новая версия pg_probackup
В обновлённой версии 2.5.6 приложения pg_probackup доработки коснулись недавно появившейся команды catchup. Для неё был добавлен флаг --dry-run, позволяющий оценить размер передаваемых файлов данных без внесения изменений на диск. Также изменён уровень детализации протоколирования некоторых сообщений catchup для удобства чтения журнала пользователем.
Обновлённый модуль ptrack
Модуль ptrack, делающий работу pg_probackup более эффективной, был обновлён до версии 2.3.0: оптимизирована загрузка карты PTRACK, чтобы избежать замедления загрузки всей базы данных в отдельных случаях.
Триггеры событий для обеспечения безопасности
Наша команда продолжает реализовывать функциональность, которая препятствует несанкционированному доступу к СУБД. Помимо специального модуля pg_proaudit и расширенных политик аутентификации, начиная с версии 14.2.1 доступны событийные триггеры.
Они срабатывают при входе пользователя, прошедшего проверку подлинности. Эта функциональность может использоваться для проверки подключения и назначения ролей в зависимости от обстоятельств или для инициализации данных сеанса. Событие 'login' происходит, когда аутентифицированный пользователь входит в систему.
Стоит отметить, что любые ошибки в процедуре триггера для этого события могут помешать успешному входу в систему. Такие ошибки можно исправить, перезапустив сервер в однопользовательском режиме (поскольку триггеры событий в этом режиме отключены).
Событийный триггер 'login' также срабатывает на резервных серверах. Во избежание проблем с подключением к резервным серверам, работающие на них триггеры входа не должны ничего писать в базу данных.
Ожидается, что аналогичная функциональность будет включена в PostgreSQL 16.
Подробнее о триггерах событий можно почитать в официальной документации.
Устранена уязвимость CVE-2022-1552
Александр Лахин из Postgres Professional обнаружил уязвимость, актуальную для более ранних версий PostgreSQL вплоть до 10-й (PostgreSQL 10 поддерживается до ноября этого года). Об этой уязвимости мы уже упоминали ранее в Postgresso №41:
При работе привилегированного пользователя с объектами другого пользователя, команды REINDEX, CREATE INDEX, REFRESH MATERIALIZED VIEW и CLUSTER отрабатывали недостаточно безопасно. Это же относится и к autovacuum, и pg_amcheck. Они активировали релевантную защиту (заключали процессы в песочницу операций, ограниченных соображениями безопасности — security restricted operation sandbox) или слишком поздно, или вообще не активировали её. Если у атакующего были привилегии создавать не временные объекты хотя бы в одной схеме, он мог запустить под суперпользователем зловредные SQL-функции.
Уязвимость устранена в Postgres Pro Enterprise 14.2.1 (и последующих версиях), а также в PostgreSQL 14.3 (и последующих версиях). Наиболее очевидный и надёжный способ устранения рисков - обновление до новейших версий.
Проверка соединения клиент-сервер при выполнении запроса
При включении параметра client_connection_check_interval выполняется проверка состояния сокета, которая позволяет раньше прерывать длительные запросы, если ядро сообщает, что соединение закрыто. Начиная с версии Postgres Pro Enterprise 14.2.1 унаследована PostgreSQL-реализация периодической проверки соединения клиент-сервер во время выполнения запроса.
Параметр client_connection_check_interval теперь фактически отключён по умолчанию.
Подробнее о нём можно прочитать в документации.
Более подробно об отличиях Postgres Pro Enterprise 14 от PostgreSQL можно почитать здесь.
Напоминаем, что каждый выпуск Postgres Pro Enterprise включает все возможности соответствующей версии PostgreSQL, поэтому уместно напомнить и о ключевых возможностях релиза 14 вообще.
Повышение масштабируемости клиентских соединeний GetSnapshotData()
Функция GetSnapshotData() возвращает снимок данных, на основании которого определяется, какие строки должны быть видны, а какие - нет. В PostgreSQL снимок данных включает в себя список активных транзакций, и при большом числе сеансов это могло вызывать проблемы масштабируемости.
В версию 14 вошёл патч Андреса Фройнда, который решил существенно переработать внутренние структуры памяти и алгоритмы для оптимизации работы функции GetSnapshotData().
Общая структура поддержки индексной нотации для любых типов данных
До PostgreSQL 14 индексная нотация была доступна только для работы с массивами. Между тем, она могла бы существенно упростить взаимодействие с другими типами данных, в первую очередь - с JSONB. Патчи Дмитрия Долгова реализуют общую структуру поддержки индексной нотации, а также реализацию индексной нотации для типов JSONB и HSTORE.
Теперь вместо использования специальных функций и операций, для обращения к данным и записи в JSONB можно использовать индекcную нотацию. Более подробно о ней можно прочесть в статье-обзоре Павла Лузанова.
Предопределённые роли pg_read_all_data и pg_write_all_data
Роль pg_read_all_data может выручить тогда, когда нужно дать пользователю полный доступ только на чтение данных. Роль pg_write_all_data дает права INSERT, UPDATE, DELETE на все таблицы, представления и последовательности.
Это удобно и правильно с точки зрения безопасности - в случае использования этих предопределённых ролей не придётся рисковать, предоставляя рядовому сотруднику компании привилегии суперпользователя. Подробнее о них можно узнать в документации.
Единый идентификатор запроса в ядре и модулях
Использование единого идентификатора запроса для ядра PostgreSQL и расширений открывает возможности, например, для соединения представлений pg_stat_activity и pg_stat_statements.
Разработчики расширений теперь могут пользоваться единым идентификатором, который вычисляется на сервере. Есть возможность добавить этот идентификатор и в журнал сервера с помощью спецпоследовательности %Q в log_line_prefix.
Несколько примеров операций с идентификатором запроса можно найти в статье Павла Лузанова.
Подпрограммы на языке SQL
Подпрограммы на языке SQL в PostgreSQL 14 приведены в соответствие с требованиями SQL-стандарта для обеспечения совместимости с другими СУБД. Краткий перечень изменений:
Нет конструкции AS $$ текст функции $$.
Новое ключевое слово RETURN для возврата значения.
При создании функции команда предварительно разбирается, результат разбора сохраняется в pg_proc.prosqlbody.
Текст функции не сохраняется в pg_proc.prosrc.
Если раньше текст подпрограммы интерпретировался заново, то теперь этого не происходит.
О некоторых других следствиях приведения SQL-подпрограмм к стандарту можно почитать здесь.
Улучшена заморозка с COPY WITH FREEZE
В PostgreSQL 14 усовершенствована предыдущая реализация копирования с заморозкой. COPY WITH FREEZE не просто загружает данные в таблицу - добавленные строки сразу помечаются как замороженные. Таким образом, после загрузки в таблице нет «мёртвых» строк и нечего замораживать. Получается, что последующей очистке нечего делать в таблице, пока не накопятся новые изменения. Подробнее об этом новшестве можно узнать здесь.
К сожалению, у этой реализации по-прежнему есть ограничения. Основная таблица замораживается полноценно, но TOAST-таблица, если она есть, это изменение не получит, и последующая очистка будет переписывать все страницы. Подробнее о том, почему часть уже проделанной работы не вошла в 14-й релиз, написано в официальном списке рассылки.
Улучшения секционирования: ALTER TABLE… DETACH PARTITION CONCURRENTLY
Отключение секции на лету без остановки приложения стало возможным. Команда DETACH PARTITION CONCURRENTLY выполняется в две транзакции. Первая помечает секцию (pg_inherits.inhdetachpending) как планируемую к отключению. Это дает возможность параллельным запросам, которые уже выполняются или только запланировали доступ к секции, отработать не меняя плана, а все новые запросы уже не будут «видеть» секцию. Теперь нужно подождать завершения всех транзакций, работающих с таблицей и начатых до изменения признака pg_inherits.inhdetachpending, и во второй транзакции непосредственно отключить секцию.
Необходимо помнить, что такая реализация предполагает ряд ограничений. DETACH PARTITION CONCURRENTLY не может выполняться в начатой транзакции. И, как следствие, команда не может вызываться в функции. Более того, реализация такова, что и из процедуры не может вызываться. Если захочется написать обвязку вокруг команды (например добавление новой секции и сразу отключение и удаление старой), то придется это делать скриптами на клиенте.
Подробнее об этой команде можно прочитать в статье-обзоре Павла Лузанова.
Обработка UPDATE и DELETE для секционированных таблиц
Чтобы оптимизировать работу с секционированными таблицами и ускорить работу запросов на обновление и удаление, было принято решение переписать узел плана ModifyTable, используемый для выполнения любых команд UPDATE и DELETE.
В результате этих доработок запросы на обновление и удаление стали работать аналогично запросам на выборку.
Фразы CYCLE и SEARCH для рекурсивных запросов
Добавление фраз CYCLE и SEARCH - ещё один шаг на пути приведения PostgreSQL к требованиям SQL-стандарта. Нельзя сказать, что эти фразы добавляют какие-то новые возможности для рекурсивных запросов, но они существенно упрощают их написание. Не требуется явно объявлять служебные столбцы и следить за их правильным формированием. Это удобно и сокращает количество потенциальных ошибок.
Почитать о фразах CYCLE и SEARCH можно в нашем блоге.
Логическая репликация: потоковая передача данных
Встроенная логическая репликация PostgreSQL дорабатывается начиная с версии 10. Потоковую логическую репликацию начали обсуждать ещё в 2017-м, и изменения применялись в несколько этапов.
Большие объемы передачи данных в рамках одной транзакции могут привести к отставанию репликации. В PostgreSQL 14 появилась возможность объявлять публикацию, включив новый параметр STREAMING. Это даёт возможность передавать данные подписчику не дожидаясь окончания транзакций, ориентируясь на объем оперативной памяти переупорядочивающего буфера, заданный параметром logical_decoding_work_mem. Подписчик, в свою очередь, сможет применять изменения порциями и показывать их пользователям только после получения информации о фиксации транзакции.
Для реализации потребовалось очень серьезно переработать механизмы логической репликации: обработку транзакций на стороне публикации (wal sender), протокол передачи через WAL, применение данных на стороне подписчика (logical_replication_worker).
Более подробно о потоковой логической репликации в обзоре Павла Лузанова.
Логическая репликация: передача данных в двоичном формате
Возможность передавать данные в двоичном формате сделала логическую репликацию быстрее. При создании или изменении подписки надо запросить у сервера передачу двоичных данных (по умолчанию она отключена): CREATE|ALTER SUBSCRIPTION … WITH (BINARY = ON)
После включения двоичные данные будут передаваться для тех типов, у которых определены функции send/receive. В противном случае используются функции, указанные для input/output.
Новые возможности postgres_fdw
В PostgreSQL 14 был включён целый ряд новых возможностей для postgres_fdw, перечислим только основные с примерами, доступными по ссылкам:
Libpq: API для конвейерного режима работы
Протокол libpq давно поддерживает асинхронное выполнение команд. Но отправить следующую команду до получения результата от предыдущей до выхода PostgreSQL 14 было нельзя.
В этом релизе появился конвейерный режим (pipeline mode). При переключении в него приложение может ставить в очередь для отправки на сервер несколько запросов. После вызова функции синхронизации с сервером, команды выполняются в порядке постановки в очередь. В таком же порядке возвращаются результаты.
Конвейерный режим эффективен при выполнении большого количества коротких команд за счет сокращения времени на обмен с сервером. Особенно если сетевые задержки существенные. Но такой режим требует больше памяти и на клиенте, и на сервере.
Некоторые другие заметные улучшения PostgreSQL 14 перечислены в докладе Павла Лузанова на PGConf.Russia 2021, а описание всех новшеств и исправлений стоит смотреть в официальной документации.
Изменения в списке поддерживаемых ОС
Добавлена поддержка Ubuntu версии 22.04, прекращена поддержка системы Основа 2.0. Поддерживаются все основные отечественные дистрибутивы Linux. Подробнее о поддерживаемых платформах можно узнать здесь.