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

В PostgreSQL 16 перенос таблицы между схемами может занять одну команду — или превратиться в отдельный проект, если нужно копировать данные и не останавливать запись. Выбор зависит от того, меняется только пространство имён или вместе с ним структура таблицы, правила доступа и приложение.
Сначала определите, что именно переезжает
Схемы находятся внутри одной базы данных. Если нужно лишь переместить таблицу, не копируя её содержимое, обычно подходит ALTER TABLE ... SET SCHEMA. Данные физически не копируются: меняется схема, в которой PostgreSQL показывает таблицу. Индексы и связанные с таблицей ограничения перемещаются вместе с ней; принадлежащая таблице последовательность тоже переезжает.
Но схема приложения — не один объект. Представления, функции, типы и другие таблицы не переедут автоматически только потому, что ссылаются на перемещённую таблицу. Проверьте их отдельно. А если нужно создать новую таблицу, преобразовать данные или сохранить старую схему для отката, это уже копирование, а не перенос.
Термин: схема — именованное пространство внутри базы данных. Она помогает разделять объекты и управлять доступом, но сама по себе не изолирует данные так, как отдельная база.
Три подхода и цена каждого
| Подход | Когда подходит | Цена и риск |
|---|---|---|
| Переместить таблицу | Структура сохраняется, нужна новая схема | Короткая операция, но может ждать блокировки; зависимости и права нужно проверить |
| Скопировать через INSERT ... SELECT | Нужна новая таблица или преобразование данных | Чтение и запись всех строк создают нагрузку, занимают место и генерируют WAL |
| Копировать и переключить запись | Нельзя надолго останавливать приложение | Нужны синхронизация изменений, контроль расхождений и план отката |
Главный вопрос — не «как переместить таблицу», а «в какой момент приложение начнёт читать и писать в новое место и как вы докажете, что данные не разошлись».
Подход 1: переместить таблицу командой
Для PostgreSQL 16 простой перенос выглядит так. Выполняйте его с ролью, у которой есть право изменить таблицу и создать объекты в целевой схеме.
BEGIN;
ALTER TABLE legacy.orders SET SCHEMA app;
COMMIT;После переноса таблица доступна как app.orders. Команда не переписывает все строки, но это не означает, что её можно незаметно выполнить в любой момент: изменение структуры требует блокировки и может ждать запросы, которые уже работают с таблицей. Для крупной или загруженной системы заранее проверьте активные транзакции и выделите окно переключения.
До команды убедитесь, что схема назначения существует. Проверьте также SQL приложения: явные обращения к legacy.orders после переноса перестанут находить таблицу. Не полагайтесь на search_path как на единственную защиту: при одинаковых именах в нескольких схемах запрос может обратиться не к тому объекту.
Подход 2: скопировать строки в новую таблицу
Копирование выбирают, если в целевой схеме будет другая структура, нужно преобразовать значения или требуется оставить исходную таблицу для отката. Сначала создайте целевую таблицу и проверьте её ограничения, индексы и права. Затем переносите данные явным списком колонок:
INSERT INTO app.orders (id, customer_id, created_at, total)
SELECT id, customer_id, created_at, total
FROM legacy.orders;Названия и типы колонок в примере условные: замените их на реальные поля своей таблицы. Явный список безопаснее SELECT *: если состав таблиц различается или позже изменится порядок колонок, соответствие останется видимым. До запуска решите, что делать с конфликтами ключей и значениями, которые не проходят ограничения целевой таблицы. Не добавляйте ON CONFLICT DO NOTHING только ради того, чтобы запрос завершился: так можно незаметно потерять часть строк.
Если таблица велика, одна транзакция может долго удерживать ресурсы и раздувать журнал предзаписи. Копирование порциями снижает размер отдельных транзакций, но требует устойчивого ключа, например возрастающего id, и ясного плана для строк, изменившихся во время переноса. Если приложение продолжает писать в исходную таблицу, простое копирование один раз не гарантирует актуальность копии.
Проверьте результат до переключения
Минимальная проверка — сравнить количество строк, отдельно проверить диапазоны ключей и важные для приложения агрегаты. Например, если сумма заказа критична, сравните суммы в источнике и копии, а не только число строк. Сверка по снимку данных имеет смысл, пока источник не меняется; при активной записи расхождения могут быть нормальными и требуют отдельной синхронизации.
SELECT 'legacy' AS source, count(*) FROM legacy.orders
UNION ALL
SELECT 'app' AS source, count(*) FROM app.orders;Равное число строк не доказывает, что строки совпадают. Для критичных данных выберите дополнительные проверки по ключам и бизнес-правилам, а перед переключением зафиксируйте момент, после которого запись в старую таблицу запрещена или изменения гарантированно попадают в новую.
Подход 3: перенести без долгой остановки записи
Когда приложение должно оставаться доступным, обычно используют поэтапный переезд: создают целевую таблицу, копируют старые строки, синхронизируют новые изменения, сверяют данные и только потом переключают приложение. Это часто называют cutover — моментом, когда рабочая система начинает использовать новое место.
Ключевая сложность — не первоначальная копия, а изменения, которые происходят параллельно с ней. Если записи идут одновременно в обе таблицы, сбой между двумя операциями может оставить их в разном состоянии. Синхронизацию нужно проектировать и тестировать для конкретного приложения: например, на уровне его кода или с помощью отдельного механизма репликации. Универсальный триггер «на все случаи» здесь опасен — особенно при обновлении и удалении строк.
Перед переключением задайте проверяемые условия: очередь изменений обработана, контрольные показатели совпали, приложение прошло тесты на новой таблице, а у команды есть способ вернуть трафик назад. Не удаляйте источник сразу после cutover: сначала убедитесь, что новое место стабильно, и только затем планируйте очистку.
Что ломается чаще всего
- Приложение продолжает обращаться к старой схеме. Поиск по конфигурации и SQL должен найти явные имена объектов; отдельно проверьте фоновые задания и отчёты.
- У роли нет доступа. Право на таблицу и право использовать целевую схему — разные вещи. Проверьте подключение от имени реальной роли приложения, а не администратора.
- Не перенеслись соседние объекты. Представление или функция может остаться в прежней схеме. Проверьте зависимости и поведение после переноса на тестовой копии.
- Копия отстаёт от источника. Если запись продолжалась во время копирования, сравните данные после синхронизации, а не только сразу после первого INSERT.
- Переключение упёрлось в долгую транзакцию. Перед изменением проверьте, нет ли запросов, удерживающих блокировки, и заранее определите допустимое время ожидания.
Когда какой способ выбирать
Если таблица остаётся той же, а меняется только схема, выбирайте перемещение и заранее подготовьте обновление обращений приложения и прав. Если нужно изменить структуру или получить независимую копию, используйте копирование и предусмотрите нагрузку на диск и WAL. Если нельзя остановить запись надолго, планируйте синхронизацию изменений как отдельную часть миграции: без неё копия может оказаться устаревшей уже в момент переключения.
В PostgreSQL 16 детали поведения команд и ограничений лучше сверять с документацией именно этой версии. В более новых выпусках проверяйте документацию своей версии и сначала прогоняйте миграцию на тестовой базе: структура зависимостей и настройки проекта могут изменить план работ.
Что делать дальше
Составьте список объектов, которые используют исходную таблицу, и решите, будет ли запись остановлена на время переноса. Затем выполните пробную миграцию на копии базы, замерьте длительность, блокировки и объём WAL, проверьте доступы от имени приложения. В проде следите за ошибками запросов, задержкой и расхождением контрольных показателей до тех пор, пока откат не перестанет быть нужен.
Аналитик звонков: Разбор записи звонка по этапам сделки: где сорвалось, что упущено, три исправляемые рекомендации с цитатами.
Спросить за 90 ₽Источники: PostgreSQL 16: ALTER TABLE, PostgreSQL 16: схемы
Частые вопросы
Команда SET SCHEMA копирует данные?
Нужно ли останавливать приложение при перемещении таблицы?
Переместятся ли вместе с таблицей представления и функции?
Что делать, если приложение пишет в исходную таблицу во время копирования?
Можно ли выполнить эти команды в другой версии PostgreSQL?
Как доказать, что копия совпадает с исходной?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.