ESPN DeportesSan Francisco disfrutan de otra victoria y un récord invictoESPNCFB top 25 betting lines: Bama slim home favorite vs. UGA; Oregon favored vs. UCLAPunchPolice probe officers caught on hidden camera extorting Lagos dispatch riderThe Jerusalem PostWill Yemen's massive new anti-Houthi offensive succeed in bid to reclaim lost territory? - analysisDaily MaverickLOCAL ELECTIONS 2026: Manifesto test: IFP offers more financial support for traditional leadersRTP DesportoQuatro jogos, quatro vitórias. Seleção portuguesa em nova eraInquirerMarcos hopes Filipinos see sincerity in government effortsZDF heuteAktuelle Pressemitteilungen des ZDFRapplerRainy season over for 2026 as southwest monsoon ends3DNewsGoogle признала, что не все Android-приложения будут нормально работать на Googlebook с чипами Intel
The Daily Newsstand · Free, Always
Monday, October 5, 2026

PostgreSQL 19: Коммитфест 2026-03 Часть 5.3 (DBA3, DBS)

Translate

Продолжаем обзор мартовского коммитфеста 19-й версии. В третьей статье серии рассмотрим изменения, относящиеся к материалам курсов DBA3 и DBS.

Напоминаю план статей о последнем коммитфесте 19-й версии:

Об изменениях в предыдущих коммитфестах рассказано здесь: 2025-07, 2025-09, 2025-11, 2026-01.

В этом обзоре:

pg_verifybackup, pg_waldump: чтение WAL в формате tar
commit: b15c1513984, b3cf461b3cf

pg_verifybackup и pg_waldump раньше умели анализировать WAL-файлы только в развернутом виде. Для их использования резервную копию в tar-архиве предварительно нужно было распаковать. Теперь обе утилиты читают и разбирают WAL прямо внутри tar-файла.

$ pg_basebackup --pgdata=. --format=tar
$ ls -l
total 6088948
-rw------- 1 pal pal     192411 Oct  5 12:06 backup_manifest
-rw------- 1 pal pal 6218102272 Oct  5 12:06 base.tar
-rw------- 1 pal pal   16778752 Oct  5 12:06 pg_wal.tar
$ pg_verifybackup .
backup successfully verified

Поскольку WAL-файлы теперь могут располагаться не только в каталоге, но и в архиве tar, у pg_verifybackup появился параметр --wal-path вместо прежнего --wal-directory. Параметр --wal-directory объявлен устаревшим, но пока поддерживается для обратной совместимости.

pg_stat_recovery: мониторинг репликации и восстановления
commit: 01d485b142e

Новое системное представление pg_stat_recovery показывает текущее состояние восстановления. При физической репликации восстановление выполняет процесс startup на реплике, поэтому именно на реплике и нужно смотреть в представление, которое показывает одну строку:

SELECT * FROM pg_stat_recovery\gx
-[ RECORD 1 ]------------+------------------------------
promote_triggered        | f
last_replayed_read_lsn   | F/2F000028
last_replayed_end_lsn    | F/2F000060
last_replayed_tli        | 1
replay_end_lsn           | F/2F000060
replay_end_tli           | 1
recovery_last_xact_time  | 
current_chunk_start_time | 2026-09-08 13:55:36.859622+03
pause_state              | not paused

Вне режима восстановления, например на мастере, представление не возвращает строк.

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

psql: индикатор реплики в приглашении
commit: dddbbc253b9

В приглашении psql раньше не было способа отличить подключение к реплике от основного сервера. Новый спецсимвол %i в переменных PROMPT1/PROMPT2 выводит индикатор режима (primary/standby) в приглашение:

postgres@postgres(19.0)=# \dconfig in_hot_standby
List of configuration parameters
   Parameter    | Value 
----------------+-------
 in_hot_standby | off
(1 row)
postgres@postgres(19.0)=# \set PROMPT1 [%i]:PROMPT1
[primary]postgres@postgres(19.0)=# 

При переключении на реплику приглашение автоматически меняется:

[primary]postgres@postgres(19.0)=# \c - - - 5402
You are now connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5402".
[standby]postgres@postgres(19.0)=# \dconfig in_hot_standby
List of configuration parameters
   Parameter    | Value 
----------------+-------
 in_hot_standby | on
(1 row)
[standby]postgres@postgres(19.0)=# 

Это особенно полезно, когда в строке подключения указано несколько узлов.

pg_createsubscriber --logdir: запись диагностики в файлы
commit: d6628a5ea0a, 6b5b7eae3ae, 847336ba53a

Утилита pg_createsubscriber (преобразующая физическую реплику в логического подписчика) выводила все диагностические сообщения только на консоль, что не всегда удобно при автоматизации запуска. Новый параметр --logdir перенаправляет вывод в файлы:

$ pg_createsubscriber -D . -P "host=localhost port=5401" -d demo --logdir=log

Внутри каталога log создается каталог с временной меткой запуска, в котором и создаются файлы журналов.

$ ls -lR log
log:
total 8
drwx------ 2 pal pal 4096 Oct  5 13:10 20261005T121108.763
drwx------ 2 pal pal 4096 Oct  5 13:11 20261005T131143.866

log/20261005T121108.763:
total 4
-rw------- 1 pal pal 403 Oct  5 13:10 pg_createsubscriber_internal.log

log/20261005T131143.866:
total 8
-rw------- 1 pal pal    0 Oct  5 13:11 pg_createsubscriber_internal.log
-rw------- 1 pal pal 4375 Oct  5 13:11 pg_createsubscriber_server.log

Публикации: исключение отдельных таблиц
commit: fd366065e06, 493f8c6439c, 5984ea868ee

При создании публикации можно указать фразу FOR ALL TABLES, чтобы включить все таблицы базы данных. Но что, если нужны все таблицы, кроме нескольких?

В 19-й версии в командах CREATE|ALTER PUBLICATION появилась возможность исключить из публикации отдельные таблицы:

CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE seats, boarding_passes);
\dRp+
                                                       Publication pub
  Owner   | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description 
----------+------------+---------------+---------+---------+---------+-----------+-------------------+----------+-------------
 postgres | t          | f             | t       | t       | t       | t         | none              | f        | 
Except tables:
    "bookings.boarding_passes"
    "bookings.seats"

Подписка логической репликации: подключение через postgres_fdw
commit: 8185bb53476

Попробуйте найти изменения в синтаксисе команды CREATE SUBSCRIPTION:

\h create subscription
Command:     CREATE SUBSCRIPTION
Description: define a new subscription
Syntax:
CREATE SUBSCRIPTION subscription_name
    { SERVER server_name | CONNECTION 'conninfo' }
    PUBLICATION publication_name [, ...]
    [ WITH ( subscription_parameter [= value] [, ... ] ) ]

А они есть. Для подключения к серверу публикации теперь можно вместо строки подключения (CONNECTION) указать имя внешнего сервера (SERVER). Под внешним сервером понимается postgres_fdw.

Так параметры подключения и подписки можно сопровождать независимо. Для нескольких подписок к одному серверу публикации не нужно каждый раз указывать строку подключения. Изменить строку подключения можно в одном месте, не меняя подписки. Дополнительно можно задействовать функционал сопоставления пользователей (USER MAPPING) для разделения доступа.

Итак, у нас есть публикация pub в базе данных demo:

publisher=# \dRpx pub
List of publications
-[ RECORD 1 ]-----+---------
Name              | pub
Owner             | postgres
All tables        | t
All sequences     | f
Inserts           | t
Updates           | t
Deletes           | t
Truncates         | t
Generated columns | none
Via root          | f

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

postgres@subscriber=# CREATE EXTENSION postgres_fdw;
postgres@subscriber=# CREATE SERVER demo_server
  FOREIGN DATA WRAPPER postgres_fdw
  OPTIONS (host 'localhost', port '5401', dbname 'demo');

Создадим роль с необходимыми правами (но без прав суперпользователя), которая будет создавать подписку логической репликации:

postgres@subscriber=# CREATE ROLE alice LOGIN;
postgres@subscriber=# GRANT pg_create_subscription TO alice;
postgres@subscriber=# GRANT CREATE ON DATABASE demo TO alice;
postgres@subscriber=# GRANT USAGE ON SCHEMA bookings TO alice;
postgres@subscriber=# GRANT ALL ON ALL TABLES IN SCHEMA bookings TO alice;
postgres@subscriber=# GRANT USAGE ON FOREIGN SERVER demo_server TO alice;

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

postgres@subscriber=# CREATE USER MAPPING FOR alice
  SERVER demo_server
  OPTIONS (user 'postgres', password 'postgres');

Теперь alice может создать подписку, указывая внешний сервер вместо строки подключения:

alice@subscriber=> CREATE SUBSCRIPTION sub
  SERVER demo_server
  PUBLICATION pub
  WITH (run_as_owner = true);

wal_sender_shutdown_timeout: время ожидания передачи данных WAL при остановке сервера
commit: a8f45dee917

При остановке сервера процессы walsender должны передать все изменения подключенным к ним процессам на репликах. Однако иногда они надолго зависают в ожидании ответа от получателя. Особенно это касается логической репликации, когда процесс, применяющий изменения на подписчике, ждет блокировок.

Новый параметр wal_sender_shutdown_timeout позволяет задать время ожидания передачи данных WAL. По умолчанию время ожидания не ограничено:

\dconfig+ wal_sender_shutdown_timeout
                      List of configuration parameters
          Parameter          | Value |  Type   | Context | Access privileges 
-----------------------------+-------+---------+---------+-------------------
 wal_sender_shutdown_timeout | -1    | integer | user    | 
(1 row)

wal_receiver_timeout: установка на уровне пользователя и на уровне подписки
commit: 8a6af3ad087, fb80f388f4a

Если у сервера несколько подписок на разные серверы публикации, для каждой из них можно задать свое время ожидания, по истечении которого прерываются неактивные соединения репликации.

Во-первых, можно указать новый параметр подписки wal_receiver_timeout в командах CREATE|ALTER SUBSCRIPTION. Во-вторых, параметр конфигурации wal_receiver_timeout теперь можно задавать на уровне пользователя-владельца подписки (context=user), а не всей системы (sighup), как было раньше.

SSL: SNI на стороне сервера
commit: 4f433025f66, 4abcdc1bbeb

Поддержка SNI на стороне клиента была добавлена еще в 14-й версии через параметр sslsni библиотеки libpq. Этим могли пользоваться только внешние TLS-прокси, стоящие перед сервером PostgreSQL. Сам же сервер PostgreSQL эту информацию игнорировал и всегда отдавал клиенту один и тот же сертификат, настроенный в postgresql.conf.

В 19-й версии сервер PostgreSQL получил возможность отдавать разные SSL-сертификаты в зависимости от того, какое имя сервера указывает клиент при подключении. Это может быть полезно для облачных провайдеров, у которых несколько разных виртуальных серверов PostgreSQL обслуживаются с одного IP-адреса и порта.

Для настройки SNI на сервере нужно включить новый параметр ssl_sni:

\dconfig+ ssl_sni
            List of configuration parameters
 Parameter | Value | Type | Context | Access privileges 
-----------+-------+------+---------+-------------------
 ssl_sni   | off   | bool | sighup  | 
(1 row)

Кроме того, нужно прописать соответствие имен серверов сертификатам и ключам в новом конфигурационном файле pg_hosts.conf. После инициализации кластера баз данных файл пуст:

$ cat $PGDATA/pg_hosts.conf
# PostgreSQL SNI Hostname mappings
# ================================

# HOSTNAME       SSL CERTIFICATE             SSL KEY     SSL CA       PASSPHRASE COMMAND         PASSPHRASE COMMAND RELOAD

Если ssl_sni включен и в pg_hosts.conf есть записи, они имеют приоритет перед параметрами SSL из postgresql.conf.

GRANT/REVOKE … GRANTED BY
commit: dd1398f1378

Команды GRANT и REVOKE для выдачи привилегий поддерживают фразу GRANTED BY, в которой указывается, какая именно роль должна выдать/отозвать привилегию. Наличие фразы GRANTED BY требует стандарт SQL. Вот только на деле можно было указать лишь текущую роль. При указании других ролей выдавалась ошибка:

ERROR:  grantor must be current user

В 19-й версии можно выдавать/отзывать привилегии от имени указанной роли, при условии:

  • У роли в GRANTED BY действительно есть права выдавать/отзывать привилегии, и она сама могла бы выполнить эту команду.

  • Роль, выполняющая команду, наследует привилегии роли из GRANTED BY (напрямую или через цепочку членства с INHERIT).

Пример с ролями: alice, bob, charlie и dave.

Суперпользователь предварительно создал таблицу и выдал alice и bob привилегию SELECT с правом передачи другим ролям:

postgres=# CREATE TABLE test (id int);
postgres=# GRANT SELECT ON test TO alice WITH GRANT OPTION;
postgres=# GRANT SELECT ON test TO bob WITH GRANT OPTION;

А также включил роль charlie в роли alice и bob с параметром членства INHERIT:

postgres=# GRANT alice TO charlie WITH INHERIT true, SET false;
postgres=# GRANT bob TO charlie WITH INHERIT true, SET false;

Теперь роль charlie может раздавать привилегию на чтение таблицы другим ролям как от имени alice, так и от имени bob.

charlie=> GRANT SELECT ON test TO dave GRANTED BY bob;
GRANT
charlie=> \dp test
                                 Access privileges
 Schema | Name | Type  |     Access privileges      | Column privileges | Policies 
--------+------+-------+----------------------------+-------------------+----------
 public | test | table | postgres=arwdDxtm/postgres+|                   | 
        |      |       | alice=r*/postgres         +|                   | 
        |      |       | bob=r*/postgres           +|                   | 
        |      |       | dave=r/bob                 |                   | 
(1 row)

А также отзывать привилегию:

charlie=> REVOKE SELECT ON test FROM dave GRANTED BY bob;
REVOKE

Раньше в такой ситуации не было определено, от чьего имени будет выдана привилегия.

Предупреждение об истечении срока действия пароля
commit: 1d92e0c2cc4

Новый параметр password_expiration_warning_threshold управляет выдачей предупреждения о приближающемся истечении срока действия пароля. По умолчанию это 7 дней:

\dconfig+ password_expiration_warning_threshold
                           List of configuration parameters
               Parameter               | Value |  Type   | Context | Access privileges 
---------------------------------------+-------+---------+---------+-------------------
 password_expiration_warning_threshold | 7d    | integer | sighup  | 
(1 row)

А само предупреждение выглядит так:

postgres=# \set tomorrow `date -d "tomorrow" "+%Y%m%d"`
postgres=# ALTER ROLE alice VALID UNTIL :'tomorrow';
ALTER ROLE
postgres=# \c - alice
Password for user alice: 
WARNING:  role password will expire soon
DETAIL:  The password for role "alice" will expire in 5 hours.
You are now connected to database "postgres" as user "alice".

Пароли MD5: продолжение подготовки к снятию с поддержки
commit: bc60ee86066

Еще с 18-й версии при установке пароля, зашифрованного по MD5, выдается предупреждение о том, что поддержка паролей MD5 будет снята в будущих версиях. Но пароль все же устанавливался, и им можно было пользоваться.

Теперь предупреждение выдается и при подключении с таким паролем.

\connect - alice
Password for user alice: 
WARNING:  authenticated with an MD5-encrypted password
DETAIL:  MD5 password support is deprecated and will be removed in a future release of PostgreSQL.
You are now connected to database "postgres" as user "alice".

Предупреждения можно отключить параметром md5_password_warnings. Но о переходе на SCRAM-SHA-256 точно стоит задуматься.

pg_[read|write]_all_data: теперь и для больших объектов
commit: d9819760279

Предопределенные роли pg_read_all_data и pg_write_all_data раньше не распространялись на большие объекты (Large Objects). В результате роль без прав суперпользователя, но включенная в pg_read_all_data, не могла сделать полную копию базы данных, в которой есть большие объекты.

Теперь роли pg_read_all_data и pg_write_all_data дают доступ к большим объектам на чтение и на запись соответственно.

psql: комментарии для публикаций, подписок и расширенной статистики
commit: aecc558666a

Раньше не было возможности посмотреть командами psql комментарии к публикациям, подпискам и объектам расширенной статистики. Теперь комментарии к этим объектам появились в соответствующих командах \dRp+ (публикации), \dRs+ (подписки) и \dX+ (расширенная статистика):

CREATE PUBLICATION pub FOR ALL SEQUENCES;
COMMENT ON PUBLICATION pub IS 'Последовательности';
\dRp+x
Publication pub
-[ RECORD 1 ]-----+-------------------
Owner             | postgres
All tables        | f
All sequences     | t
Inserts           | t
Updates           | t
Deletes           | t
Truncates         | t
Generated columns | none
Via root          | f
Description       | Последовательности

На этом пока все. В следующем и последнем обзоре серии рассмотрим изменения, относящиеся к языку SQL, а также курсам DEV1 и DEV2.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.