
Статья подготовлена вместе с экспертами
Дмитрий Ковальчук, менеджер продукта

Версию PostgreSQL 14 пора переносить: 12 ноября 2026 года она уходит в End-of-life (EOL), то есть её поддержка официально прекращается. Нужно либо обновляться, либо наконец принимать решение о переезде в облако. Самостоятельный апгрейд мажорных версий требует остановки сервиса на десятки минут, ручной правки расширений и последующих недель на настройку автоматических бэкапов, мониторинга, репликации. Managed DBaaS снимает эту работу: версию, резервные копии, реплики и апгрейды берёт на себя платформа. Остаётся вопрос: как перенести production-базу без потери данных и без простоя на часы.
В статье — пошаговый план для DBA, DevOps-инженеров и разработчиков, которые мигрируют PostgreSQL в Managed PostgreSQL в VK Clouds. Команды проверены на PostgreSQL 14–17, акцент — на двух рабочих сценариях: дамп-восстановление для разовых переносов и логическая репликация для миграции без простоя.

Дмитрий Ковальчук, менеджер продукта

Дарья Шибкова, менеджер продукта
До первой команды pg_dump фиксируем шесть параметров: версию PostgreSQL, общий объём данных, количество таблиц и индексов, список расширений, кастомные процедуры и триггеры, внешние зависимости вроде FDW. Это нужно, чтобы реалистично оценить длительность миграции.
sql
-- Размер БД и топ-10 таблиц по объёму SELECT pg_size_pretty(pg_database_size('mydb')); SELECT schemaname, relname, pg_size_pretty(pg_total_relation_size(relid)) AS total_size FROM pg_catalog.pg_statio_user_tables ORDER BY pg_total_relation_size(relid) DESC LIMIT 10; -- Установленные расширения SELECT extname, extversion FROM pg_extension; -- Список таблиц публичной схемы SELECT schemaname, tablename FROM pg_tables WHERE schemaname = 'public'; -- Активные соединения и состояния SELECT pid, usename, state, query_start FROM pg_stat_activity;
Берём объём хранилища с запасом 2× от текущего: учитываем рост во время миграции, временные WAL-сегменты, индексы после REINDEX. Пиковые IOPS снимаем через pg_stat_io — это показывает не оценочную, а реальную картину нагрузки. Чтобы выбрать корректное значение RAM-инстанса, оцениваем shared_buffers (обычно 25% от RAM инстанса).
Облачный PostgreSQL имеет определенный набор доступных расширений, который может быть расширен по запросу, поэтому совместимость проверяем до миграции, а не во время cutover (переключения между базами).
Есть два рабочих подхода:
Для production-систем с пользовательской нагрузкой подойдёт только логическая репликация. Дамп оставляем для разовых задач и небольших БД.
Раздел «Базы данных» → «Инстансы баз данных», нажимаем «Добавить». Выбираем версию PostgreSQL. Мы рекомендуем версию, совпадающую с исходной или выше. На 2026 год актуальны мажоры 15–17, актуальный список поддерживаемых мажоров уточняйте в DBaaS VK Cloud. При переезде учитывайте, что 14 версия перейдет в EOL с 14 — 12 ноября 2026. Также выбираем конфигурацию vCPU/RAM, объём диска с запасом 2×, зону доступности, виртуальную сеть для подключения.
Конфигурация выбирается на том же шаге: Single (одиночный инстанс), Master-Replica или кластер с автоматическим failover. Для PostgreSQL 16 доступна мультизональная конфигурация с повышенной отказоустойчивостью. PostgreSQL в облаке разворачивается за несколько минут — без ручной установки, настройки репликации и бэкапов.



Порт 5432 открываем только для IP приложений и машины миграции — настраивается в разделе «Виртуальные сети» → «Настройки firewall». Выставлять его в открытый интернет нельзя — это базовое требование безопасности. Между сервисами внутри облака подключение идёт через виртуальную сеть, что снижает задержку и не тарифицируется как исходящий трафик.

Сверяем список расширений из исходной БД (SELECT extname FROM pg_extension) с поддерживаемыми базами данных в VK Cloud. Стандартный набор доступен: PostGIS, pg_trgm, uuid-ossp, hstore, pgcrypto — последние три входят в бандл postgres_extensions. Из специализированных в VK Cloud DBaaS доступны: TimescaleDB (time-series), pg_partman (партиционирование), pg_hint_plan (управление планами запросов), pg_stat_kcache (статистика по системным вызовам), pgBadger (анализ логов), JsQuery. Полный актуальный список и версии — в документации VK Cloud DBaaS.
Этот метод — основной для разовых переносов с допустимым окном простоя. pg_dump-миграция работает на любых версиях PostgreSQL и не требует настройки репликации, но downtime растёт линейно с объёмом данных.
Формат custom (-Fc) — рабочий выбор для БД до ~500 ГБ: один файл, встроенное сжатие, селективное восстановление, возможность параллельного restore через pg_restore -j.
bash pg_dump -h SOURCE_HOST -U postgres -d mydb -Fc \ --no-owner --no-privileges \ --no-publications --no-subscriptions \ -f mydb_backup.dump
Ключевые параметры:
Флаг -j N (параллельный дамп) работает только с форматом directory (-Fd), а не с custom (-Fc) — это частая ошибка. Для БД больше 500 ГБ используем directory-формат:
bash
pg_dump -h SOURCE_HOST -U postgres -d mydb -Fd -j 4 \ --no-owner --no-privileges \ --no-publications --no-subscriptions \ -f mydb_backup_dir
Оптимум -j — vCPU - 1 на источнике, или 4–6 для 8-ядерного сервера. max_connections на источнике должен быть не меньше jobs + 1, иначе дамп прервётся на старте.
Три рабочих варианта:
Прямая передача через pipe: bash
pg_dump -h SOURCE_HOST -U postgres mydb -Fc \ --no-owner --no-privileges \ --no-publications --no-subscriptions \ | pg_restore -h TARGET_HOST -U postgres -d mydb
bash
pg_restore -h TARGET_HOST -U postgres -d mydb \ -Fc -j 4 --no-owner --no-privileges \ mydb_backup.dump
Параллельное восстановление (-j 4) ускоряет процесс в 3–4 раза на 8-ядерном целевом инстансе.
После восстановления — обязательный набор проверок: sql
-- Сверка количества строк по ключевым таблицам SELECT 'orders' AS t, COUNT(*) FROM orders UNION ALL SELECT 'users', COUNT(*) FROM users; -- Все ли индексы на месте SELECT schemaname, tablename, indexname FROM pg_indexes WHERE schemaname = 'public'; -- Обновить статистику планировщика — без этого первые запросы пойдут по плохим планам ANALYZE VERBOSE; -- Список sequences (last_value читается напрямую из самой sequence) SELECT sequence_schema, sequence_name FROM information_schema.sequences;
Этот метод — для production-систем с SLA, где окно простоя измеряется минутами, а не часами. Миграция без простоя через встроенную логическую репликацию PostgreSQL — рабочий стандарт с 2017 года.
Важно для managed-сценария. В VK Cloud изменение параметров wal_level=logical, max_replication_slots, max_wal_senders и доступ к роли с атрибутом REPLICATION не выдается — самостоятельная правка postgresql.conf в managed-сервисе ограничена. Для self-hosted источника на on-premise шаги ниже выполняются полностью.
PostgreSQL поддерживает встроенную логическую репликацию с версии 10. Принцип: исходная БД становится publisher, целевая — subscriber. Изменения (INSERT/UPDATE/DELETE/TRUNCATE) реплицируются на основе декодированных записей WAL, без побайтовой репликации файлов — поэтому версии publisher и subscriber могут различаться по мажору (только в направлении младший → старший или равный).
Ограничения, которые нужно знать заранее:
В postgresql.conf:
text
wal_level = logical max_replication_slots = 10 max_wal_senders = 10
Перезапуск PostgreSQL обязателен — все три параметра требуют рестарта, на лету не подтягиваются. В pg_hba.conf добавляем строку для пользователя репликации с конкретного IP subscriber'а:
text
host mydb replicator SUBSCRIBER_IP/32 scram-sha-256
Создаём роль и publication:
sql
-- Пользователь с правами репликации CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'strong_password'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO replicator; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO replicator; -- Publication для всех таблиц схемы CREATE PUBLICATION mypub FOR ALL TABLES;

Сначала переносим схему (без данных) в DBaaS VK Cloud — без этого CREATE SUBSCRIPTION упадёт на отсутствующих таблицах:
bash
pg_dump -h SOURCE_HOST -U postgres -d mydb --schema-only \ --no-owner --no-privileges \ --no-publications --no-subscriptions \ | psql -h TARGET_HOST_VK -U postgres -d mydb
Затем создаём subscription:
sql
CREATE SUBSCRIPTION mysub CONNECTION 'host=SOURCE_HOST port=5432 dbname=mydb user=replicator password=strong_password sslmode=require' PUBLICATION mypub;
PostgreSQL автоматически выполнит initial sync (по умолчанию copy_data = true) и перейдёт в режим потоковой репликации. Контроль состояния — на subscriber:
sql
SELECT subname, received_lsn, latest_end_lsn, (latest_end_lsn - received_lsn) AS lag_bytes FROM pg_stat_subscription;
Когда lag_bytes стабильно держится около нуля — репликация догнала источник и готова к cutover.
При правильной подготовке можно добиться окна простоя менее минуты. Для этого нужно:
sql
-- Список sequences (last_value читается напрямую из самой sequence) SELECT sequence_schema, sequence_name FROM information_schema.sequences; -- Текущее значение конкретной sequence: SELECT last_value FROM mytable_id_seq; -- На subscriber, для каждой sequence SELECT setval('mytable_id_seq', (SELECT MAX(id) FROM mytable));
sql
DROP SUBSCRIPTION mysub;
| Параметр | pg_dump / pg_restore | Логическая репликация |
| Downtime | От 30 минут до часов | Меньше 1 минуты |
| Сложность настройки | Низкая | Средняя |
| Версии PostgreSQL | Любые (с pg_upgrade при разных мажорах) | 10+ (мажоры могут различаться) |
| DDL-изменения | Полный перенос схемы | Не реплицируются автоматически |
| Sequences | Переносятся (но требуют setval после) | Не реплицируются |
| Large objects | Переносятся | Не реплицируются |
| Подходит для | Небольшие БД, разовый перенос, тест-staging | Production с SLA, высокий аптайм |
| Инструменты | pg_dump, pg_restore (в дистрибутиве) | Встроено в PostgreSQL 10+ |
Практическое правило: до 100 ГБ и при окне 1–2 часа — pg_dump/pg_restore. От 100 ГБ или при требовании к минимальному downtime — встроенная логическая репликация.
Типовые ошибки накапливаются на стыке подготовки и cutover: проблема выглядит безобидно на staging, а в production оборачивается ночным инцидентом. Разберём пять ошибок, которые встречаются чаще всего.
pg_restore не восстановит дамп из новой мажорной версии в более старую. Если source работает на PostgreSQL 16, а target — на 14, восстановление упадёт на синтаксисе или системных каталогах. Поэтому целевая версия должна быть равна исходной или выше.
Если миграция совпадает со сменой мажорной версии, есть два пути:
Для крупных баз второй вариант предпочтителен, так как обновление и переезд совмещаются в одном окне. У managed-сервиса есть нюанс: обновление мажорной версии в DBaaS VK Cloud выполняется последовательно, без пропуска промежуточных версий (10 → 11 → 12 → 13 → 14 и так далее).
pg_dump строит консистентный снапшот и ждёт, пока освободятся блокировки. Если в базе висит сессия в состоянии idle in transaction, дамп не стартует. Перед запуском дампа стоит остановить приложение или перевести приложение в read-only после чего проверить активные транзакции:
sql
SELECT pid, usename, state, xact_start, query FROM pg_stat_activity WHERE state = 'idle in transaction' AND xact_start < NOW() - INTERVAL '5 minutes';
Зависшие сессии завершаем через SELECT pg_terminate_backend(pid).
Логическая репликация не реплицирует sequences, а при восстановлении из дампа их значения могут отставать от реальных MAX(id) в таблицах. После переключения (switchover) первая же вставка падает с ошибкой «duplicate key value violates unique constraint» — последовательность автоинкрементного ключа отстаёт от данных и выдаёт уже занятое значение. Для автоинкрементного первичного ключа это критично.
Решение — пересчитать все sequences по фактическим максимумам. Скрипт, который сгенерирует SQL для всех колонок с привязанной sequence:
sql
-- Сгенерировать setval-команды для всех serial/identity-колонок SELECT format( $$SELECT setval(%L, (SELECT COALESCE(MAX(%I), 1) FROM %I.%I));$$, pg_get_serial_sequence(quote_ident(n.nspname)||'.'||quote_ident(c.relname), a.attname), a.attname, n.nspname, c.relname ) FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace JOIN pg_attribute a ON a.attrelid = c.oid WHERE c.relkind = 'r' AND n.nspname = 'public' AND pg_get_serial_sequence(quote_ident(n.nspname)||'.'||quote_ident(c.relname), a.attname) IS NOT NULL;
Сгенерированный набор setval прогоняем сразу после восстановления и перед тем, как пустить трафик приложения. Для миграций с большим числом таблиц без PK дополнительно проверяем REPLICA IDENTITY FULL — без него UPDATE и DELETE не реплицируются через логический поток.
При неверных правах подписчик просто молча не получает данные. У пользователя репликации должны быть:
Команды для подготовки:
sql
GRANT SELECT ON ALL TABLES IN SCHEMA public TO replicator;
Параллельно проверьте, что в дампе не остались чужие subscriptions и publications с исходного кластера.
В managed-окружении список расширений ограничен политикой провайдера. Если приложение опирается на postgis, pgvector или pg_cron, а в целевой DBaaS их нет, об этом стоит узнать до миграции, а не в момент pg_restore. Запрос на исходной базе:
sql
SELECT extname, extversion FROM pg_extension;
Полученный список сверяем с документацией. Для каждого неподдерживаемого расширения есть три стратегии: найти альтернативу (например, заменить pg_cron на внешний планировщик), отказаться от функционала, если он не критичен, или поднять самостоятельный инстанс на IaaS. Большие объекты реплицировать через логический поток тоже не получится: для таблиц с lo-полями придётся использовать pg_dump или физическую репликацию.
| Проверка | Команда / действие | Статус |
| Количество строк совпадает | SELECT COUNT(*) по ключевым таблицам | ☐ |
| Все индексы на месте | SELECT indexname FROM pg_indexes WHERE schemaname='public' | ☐ |
| Sequences корректны | SELECT last_value FROM | ☐ |
| Расширения установлены | SELECT extname, extversion FROM pg_extension | ☐ |
| Права пользователей настроены | \du в psql, проверить ROLE | ☐ |
| Приложение подключается и пишет | Функциональное тестирование + smoke-тесты | ☐ |
| Мониторинг и алертинг работает | Проверить дашборд VK Cloud + алерты на lag/replication | ☐ |
Чек-лист имеет смысл прогнать сначала на staging-копии, а затем повторить в production-окружении — расхождения между средами выявляются именно так.
Миграция не заканчивается командой pg_restore. Облачный PostgreSQL работает на инстансах с заранее заданным CPU, RAM и IOPS — параметры, скопированные с on-premise сервера, в этой среде дадут либо OOM (Out Of Memory), либо недозагрузку ресурсов. Адаптировать конфигурацию под облако нужно сразу после переезда, иначе production столкнётся с непредсказуемой латентностью под нагрузкой.
Стартовая конфигурация для инстанса 16 ГБ RAM выглядит так:
text
# postgresql.conf — стартовые значения для 16 GB RAM инстанса shared_buffers = 4GB effective_cache_size = 12GB work_mem = 8MB maintenance_work_mem = 1GB max_connections = 200 wal_level = replica autovacuum_vacuum_scale_factor = 0.05 track_io_timing = on
Здесь:
Главное правило: бэкап, который ни разу не восстанавливали, не существует. Тестовое восстановление в отдельный инстанс — регулярная процедура, а не разовая галочка при запуске. Минимум — раз в квартал, для критичных баз — ежемесячно.
Минимальный набор метрик, по которому видно состояние базы:
Быстрые SQL-запросы для регулярной проверки: sql
-- Cache hit ratio (должен быть > 99%) SELECT sum(blks_hit) * 100.0 / NULLIF(sum(blks_hit + blks_read), 0) AS cache_hit_ratio FROM pg_stat_database; -- Топ-10 самых долгих запросов SELECT query, calls, mean_exec_time, total_exec_time FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 10;
В управляемых базах данных VK Cloud базовые метрики уже выведены на дашборд, но pg_stat_statements и кастомные SQL-проверки стоит подключить к собственной системе алертинга — например, через Prometheus postgres_exporter. Так инцидент будет виден раньше, чем о нём сообщит пользователь.
Миграция PostgreSQL в облако перестала быть проектом на месяцы. Логическая репликация переносит нагруженную базу без простоя, дамп закрывает staging и небольшие инстансы за пару часов. Ключевые риски — забытые sequences, несовпадение мажорных версий, неполные права у роли репликации — отсекаются чек-листом перед началом работ по миграции. Managed DBaaS снимает дальнейшее обслуживание: обновления, резервные копии, настройку реплик берёт на себя платформа.
12 ноября 2026 года заканчивается поддержка PostgreSQL 14. После этой даты патчи безопасности выходить не будут. Миграция в облако решает сразу две задачи: закрывает проблему EOL и передаёт администрирование провайдеру. Остаётся настроить мониторинг, прогнать чек-лист после переезда и адаптировать конфигурацию под облачный инстанс.
Наши специалисты свяжутся с вами в ближайшее время и ответят на все вопросы.

Будем держать в курсе новостей и облачных трендов




