Почему обновление PostgreSQL больше нельзя откладыватьСообщество поддерживает каждую мажорную версию пять лет, потом выходит финальный минорный релиз, и ветка перестаёт получать исправления. Для PostgreSQL 14 это случится 12 ноября 2026 года.Чем это грозит, давайте покажем на недавнем примере: в августе 2026 года закрыли уязвимость CVE-2026-16239 с оценкой 8,8 по CVSS. Она позволяла пользователю базы выполнить произвольный код от имени системного пользователя сервера и затрагивала ветки с 14-й по 18-ю. Для 14-й исправление вошло в релиз 14.24. Следующую такую дыру после 12 ноября для 14-й уже не закроют.Но PostgreSQL 14 может работать у вас, даже если вы его специально не выбирали: в Ubuntu 22.04 LTS пакет postgresql по умолчанию ставит именно 14-ю версию, об этом пишут в разборе WZ-IT.Если база в облаке, провайдер может обновить её сам. В Yandex Managed Service for PostgreSQL кластеры начинают автоматически обновлять за три месяца до конца поддержки. Когда поддержка заканчивается, кластер переводят на последнюю поддерживаемую версию. Если обновить его нельзя, кластер останавливают.Минорное и мажорное обновление: на какую версию переходитьМинорное обновление, например с 18.5 на 18.6, простое. Вы останавливаете сервер, ставите новые бинарники и запускаете его снова. Каталог данных не меняется, так написано в разделе документации об обновлении кластера.При мажорном обновлении меняется внутренний формат хранения, и новый сервер не подхватит старый каталог данных. Понадобится дамп, pg_upgrade или логическая репликация.Целевую версию выбирайте по сроку поддержки из политики версий:ВерсияПоддержка доЧто учесть1511 ноября 2027через год придётся обновляться снова169 ноября 2028запас всего два года178 ноября 2029если приложение ещё не готово к 18-й1814 ноября 2030вышла в сентябре 2025 года, актуальный релиз 18.6195 лет с даты выходарелиз запланирован на 19 ноября 2026Для большинства систем, которые уходят с 14-й, лучше выбрать 18-ю. PostgreSQL 19 к моменту публикации ещё не вышел: первый релиз-кандидат появился 15 октября, второй намечен на 12 ноября, а общий релиз запланирован на 19 ноября.Промежуточные версии проходить не нужно, с 14-й можно сразу перейти на 18-ю. Но release notes всех пропущенных версий прочитать придётся, в первую очередь разделы Migration.Три способа обновления и сколько простоя даёт каждыйУ мажорного обновления три пути. Они по-разному тратят время и оставляют разные варианты отката.СпособПростойПуть назадpg_dumpall и восстановлениерастёт вместе с объёмом данныхстарый кластер не меняетсяpg_upgradeминуты в режиме linkзависит от режима переноса файловЛогическая репликациясекунды на переключениестарый кластер работает до переключенияДамп самый надёжный и самый медленный. В GitLab оценивали, что дамп и восстановление базы около 20 ТиБ занимают примерно сутки, об этом рассказано в докладе команды на PostgresConf 2024. Для дампа берите pg_dump и pg_dumpall из новой версии.pg_upgrade не переливает данные. Он создаёт новые системные каталоги и переиспользует старые файлы, поэтому в режиме --link укладывается в минуты, пишет документация pg_upgrade.Логическая репликация передаёт изменения строк между разными мажорными версиями. Новый кластер догоняет старый, пока тот обслуживает трафик, а простой остаётся только на переключение.Что проверить до окна обслуживанияБольшинство сорванных обновлений ломается не на самом pg_upgrade, а на окружении вокруг него.Расширения. pg_upgrade переносит определения расширений, но не ставит их библиотеки. Файлы .so под новую версию должны быть установлены до запуска, а CREATE EXTENSION в новом кластере выполнять не нужно. В гайде Netdata по сбоям pg_upgrade описана ловушка PostGIS: SQL-функция PostGIS_Full_Version() отработает без C-библиотеки, а ST_Contains упадёт. Поэтому проверяйте расширение вызовом C-функции.Блокирующие объекты. Неподтверждённые prepared transactions остановят pg_upgrade. Ещё утилита не переносит столбцы с типами reg*, кроме regclass, regrole и regtype.Контрольные суммы данных. В PostgreSQL 18 initdb включает их по умолчанию, а pg_upgrade требует одинаковую настройку у старого и нового кластера. Многие кластеры на 14-й работают без них. Новый кластер создают с initdb --no-data-checksums или включают суммы на остановленном старом кластере через pg_checksums --enable.Правила сортировки. В glibc 2.28 правила сортировки привели к стандарту ISO 14651. Индексы, построенные на старых правилах, на новой glibc могут возвращать неверные результаты, подробно об этом пишет Crunchy Data. Риск появляется, когда вместе с PostgreSQL вы меняете ОС. Дамп и логическая репликация от этой проблемы защищены: индексы строятся заново.Если цель PostgreSQL 19, сверьтесь с release notes 19-й версии. Дампы, снятые pg_dump старше 19-й версии при standard_conforming_strings = off, не загрузятся корректно. pg_upgrade откажется переносить кластер с индексами btree_gist по типам inet и cidr.Резервная копия и точка невозвратаПеред обновлением нужен бэкап, который вы уже хоть раз восстановили. Проверьте и сам инструмент резервного копирования: он тоже должен поддерживать целевую версию. Например, pgBackRest поддерживает PostgreSQL 19rc1 начиная с версии 2.59.2.У pg_upgrade есть точка невозврата, и она зависит от режима. В режиме --link старый кластер становится непригодным, как только вы запустили новый: файлы данных у них общие. В режиме --swap старый кластер разрушается уже на этапе переноса файлов. Скорость --link с нетронутым старым кластером даёт --clone. Он работает на Linux с ядром 4.5 и выше на Btrfs и XFS с поддержкой reflink, а также на macOS с APFS. Ещё документация предлагает обновлять в режиме link копию кластера или снапшот файловой системы.Пробный перенос на копии продаРепетиция показывает реальное время работы, недостающие пакеты и ошибки до начала окна обслуживания. Начните с pg_upgrade --check. Он только проверяет кластеры и не меняет данные, а запускать его можно при работающем старом сервере. Флаг режима передавайте тот же, что и в боевом запуске, иначе проверки для этого режима не выполнятся.В Debian и Ubuntu конфигурация лежит отдельно от данных, в /etc/postgresql. Поэтому путь к postgresql.conf передают через --old-options и --new-options.Прогон делайте на копии продовых данных и с тестами приложения. В GitLab весь процесс автоматизировали в Ansible и прогоняли в проде все шаги до момента переключения, замеряя время.Если на обследование и прогон не хватает своих людей, эту часть можно передать подрядчику. Centicore Group модернизирует легаси-код, базы данных и инфраструктуру и помогает перейти на актуальные инструменты и платформы. Перед передачей соберите версии, объём данных, список расширений и допустимое окно простоя: с этими вводными будет проще оценить работу.pg_upgrade: как сократить простой до минутВремя работы pg_upgrade зависит в основном от того, как утилита переносит файлы данных. Режимов пять:--copy копирует файлы, это режим по умолчанию и самый медленный;--clone клонирует файлы через reflink и не трогает старый кластер;--copy-file-range использует системный вызов copy_file_range на Linux и FreeBSD;--link создаёт жёсткие ссылки, каталоги должны лежать на одной файловой системе;--swap из PostgreSQL 18 перемещает каталоги данных целиком.--swap выигрывает на кластерах с большим числом таблиц. По разбору Fujitsu он работает при обновлении с PostgreSQL 10 и выше. Документация советует запускать его вместе с --sync-method=fsync.Флаг --jobs обрабатывает несколько баз и табличных пространств параллельно. Начинать советуют со значения, равного числу ядер CPU.Главное изменение 18-й версии касается статистики. Раньше после pg_upgrade её собирали заново для всей базы, и первое время планировщик работал вслепую. Теперь, как объясняет Павел Лузанов из Postgres Professional, основная статистика оптимизатора переносится. Не переносятся расширенная статистика из CREATE STATISTICS, статистика расширений и накопительные счётчики. Поэтому после запуска выполните две команды:pg_upgrade не копирует postgresql.conf и pg_hba.conf. Перенесите shared_preload_libraries, параметры памяти и правила доступа вручную.Логическая репликация: перенос почти без простояЛогическая репликация передаёт изменения строк, а не страницы данных, поэтому работает между разными мажорными версиями. У неё есть ограничения из документации:схема и DDL не реплицируются, их переносят через pg_dump --schema-only и замораживают на время миграции;значения последовательностей не реплицируются;large objects не передаются;реплицируются только таблицы;для UPDATE и DELETE нужен первичный ключ или другой replica identity.DDL в GitLab заморозили просто: отключили фоновые миграции на время переезда.Слабое место способа в начальной синхронизации, поэтому записывайте: сначала поднимаем физическую реплику, а потом превращаем её в логическую. С PostgreSQL 17 это делает pg_createsubscriber без повторного копирования данных. Исходный сервер, реплика и сама утилита должны быть одной мажорной версии, поэтому реплику сначала делают логической и только потом обновляют pg_upgrade. На исходном сервере нужен wal_level = logical, а max_slot_wal_keep_size советуют выставить в -1, чтобы нужные WAL не удалились.Для версий старше 17-й физическую реплику переводят в логическую вручную: через логический слот, recovery_target_lsn и подписку с copy_data = false. Схему описывает Николай Самохвалов из Postgres.ai.Последовательности: главная ловушка переключенияДанные в столбцах serial и identity реплицируются вместе с таблицей. Сами последовательности на подписчике до PostgreSQL 18 включительно остаются на стартовых значениях. После переключения первый же INSERT получит занятый идентификатор и упадёт на уникальном ключе.Последовательности синхронизируют вручную прямо перед переключением.В PostgreSQL 19 появилась синхронизация последовательностей: публикация ALL SEQUENCES и команда ALTER SUBSCRIPTION ... REFRESH SEQUENCES. Значения копируются только по явной команде, поэтому её ставят в сценарий переключения. Публиковать последовательности должен сервер на 19-й версии, так что по сценарию Fujitsu это пригодится при переходе с 19-й на 20-ю. При обновлении с 14-й или 18-й синхронизация остаётся ручной.Переключение приложенияСценарий переключения пишут по шагам и прогоняют на репетиции:Перевести старый мастер в режим «по умолчанию только чтение» и запомнить позицию WAL.Дождаться, пока подписка на новом кластере дойдёт до этой позиции.Синхронизировать последовательности.Поставить PgBouncer на паузу, переключить его на новый кластер и снять паузу.Отключить подписку на новом кластере, но не удалять её.Команда PAUSE дожидается освобождения серверных соединений, в режиме transaction pooling это конец текущих транзакций. Новые клиенты в это время ждут, а не получают ошибку. Если после RELOAD в конфиге изменился адрес базы, новые соединения пойдут на новый сервер.Этой связкой пользовались в GitLab: дождаться нулевого лага, поставить паузу, переключить, снять паузу.План отката: продумать до стартаОткат придумывают до окна обслуживания, потому что от него зависит выбор режима. Правила возврата после pg_upgrade по документации:после --check, --copy и --clone старый кластер не изменился, его можно просто запустить;после --link без запуска нового кластера достаточно убрать суффикс .old у файла global/pg_control;после --link с запуском нового кластера или после --swap, когда старый кластер объявлен небезопасным, поможет только бэкап.С логической репликацией откат простой, пока новый кластер не принял ни одной записи. Дальше нужна обратная репликация: в момент переключения старый кластер подписывают на новый. Тогда вернуться можно даже через некоторое время после переезда без потери данных. Старый кластер держите поднятым хотя бы 24-48 часов.Если в кластере Patroni и репликиФизическая репликация между разными мажорными версиями не работает, поэтому «катящееся» мажорное обновление по репликам невозможно. Эту ошибку разобрали в июле 2026 года в рассылке pgsql-admin.В документации Patroni порядок такой:Остановить Patroni.Обновить бинарники и выполнить pg_upgrade на лидере.Обновить patroni.yml.Удалить ключ initialize из DCS или выполнить patronictl remove, потому что у нового кластера другой системный идентификатор.Запустить Patroni на лидере.На репликах обновить бинарники и patroni.yml, очистить каталог данных.Запустить Patroni на репликах и дождаться копирования данных.Ускорить пересборку реплик можно через rsync, но только если лидер обновлялся в режиме --link. Самым безопасным Patroni называет полное копирование данных своими средствами.ИтогоОбновление PostgreSQL с минимальным простоем решается не флагом pg_upgrade, а подготовкой. Если допустимо окно в несколько минут и кластер один, хватит pg_upgrade в режиме --clone или --link после репетиции на копии прода. Если простой должен уложиться в секунды, нужна логическая репликация с ручной синхронизацией последовательностей и паузой в PgBouncer. В обоих случаях первым пишут план отката: он определяет, какой режим вы можете себе позволить.