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

В PostgreSQL команда переноса таблицы между схемами не копирует строки, а меняет расположение объекта в базе. Если же вы создаёте новую таблицу и переносите данные в неё, придётся отдельно разобраться с ключами, последовательностями, ограничениями и записями, которые продолжают поступать во время миграции. Ниже — практические варианты и проверки для PostgreSQL 16; точный план зависит от размера таблицы и допустимого простоя.
Сначала выберите, что именно вы переносите
Если нужно сменить схему у существующей таблицы в той же базе, используйте перенос объекта. Если нужна новая таблица — например, с другой структурой или в другой базе, — потребуется копирование строк. Эти операции часто смешивают, а затем обнаруживают, что данные скопировались, но приложение продолжает писать в старую таблицу.
Перед началом зафиксируйте исходную и целевую схемы, список таблиц и зависимостей, допустимое время блокировки и план отката. Проверьте, какие приложения, фоновые задания и отчёты обращаются к таблице. Особенно важны SQL-запросы с неквалифицированными именами вроде SELECT * FROM orders: после изменения search_path такой запрос может обратиться не к тому объекту.
Три подхода и их цена
| Подход | Когда подходит | Цена и риск |
|---|---|---|
| Переместить таблицу | Та же база, структура и данные остаются прежними | Команда короткая, но изменение может ждать блокировку и повлиять на приложение, использующее старое имя схемы |
| Скопировать таблицу целиком | Нужна отдельная копия или новая структура; объём умеренный, запись можно остановить | Нужны место, время на копирование и согласованное переключение. Внешние ключи, последовательности и права проверяются отдельно |
| Копировать порциями | Большой объём, длительное копирование одной транзакцией нежелательно | Меньше одна длинная транзакция, зато нужны контроль прогресса, повторяемость порций и синхронизация новых изменений |
Критическая развилка не в том, сколько строк в таблице, а в том, может ли приложение продолжать запись, пока вы переносите данные.
Вариант 1: переместить таблицу без копирования
Для таблицы в той же базе PostgreSQL меняет схему объекта. Строки не нужно вставлять повторно, а таблица сохраняет своё содержимое.
BEGIN;
ALTER TABLE app.orders SET SCHEMA archive;
COMMIT;
Команда переносит саму таблицу, а не все объекты, которые когда-либо с ней связаны. Индексы и ограничения таблицы остаются при ней; проверьте отдельно представления, функции, задания и SQL в приложениях. Текст динамического SQL может содержать старое имя схемы, хотя обычные зависимости PostgreSQL отслеживает как объекты.
До запуска проверьте блокировки: изменение схемы может ждать завершения чужой транзакции, а ожидающая DDL-команда способна задержать последующие запросы. Не запускайте перенос в пиковое время без наблюдения за активными сессиями. После команды проверьте, что таблица доступна по новому полному имени и что учётная запись приложения имеет нужные права на схему и таблицу.
Сам перенос не исправит запросы, которые явно указывают старую схему. Перед переключением обновите конфигурацию приложения и фоновых задач, затем проверьте журналы на ошибки обращения к старому имени.
Вариант 2: скопировать строки в готовую таблицу
Копирование подходит, если целевая таблица уже создана и содержит совместимые столбцы. Указывайте столбцы явно: так миграция не зависит от порядка полей и случайного появления нового столбца в источнике.
INSERT INTO archive.orders (id, customer_id, created_at, total)
SELECT id, customer_id, created_at, total
FROM app.orders;
Фрагмент предполагает, что столбцы существуют в обеих таблицах, а целевая таблица принимает переданные значения. Если целевой столбец объявлен как identity с режимом GENERATED ALWAYS, для переноса исходных значений потребуется синтаксис OVERRIDING SYSTEM VALUE. Проверьте определение таблицы до запуска, а не после ошибки.
Явная вставка идентификаторов не гарантирует, что последовательность целевой таблицы настроена на следующий свободный номер. Это относится и к столбцам с serial, и к identity: после копирования проверьте, откуда целевая таблица будет брать новые значения. Не переносите настройки последовательности вслепую — у разных таблиц могут быть разные последовательности и правила.
Внешний ключ не появляется автоматически только потому, что строки скопировали из таблицы с таким же именем. Проверьте целостность ссылок, уникальные ограничения, триггеры и значения по умолчанию в целевой таблице. Триггеры при вставке могут запускаться и менять данные или вызывать дополнительную нагрузку.
Как выбрать способ переключения
Для небольшой таблицы с записями, которые можно ненадолго остановить, проще согласовать короткое окно: запретить запись, скопировать данные, сверить результат и переключить приложение. Если остановить запись нельзя, одного копирования недостаточно: изменения, пришедшие после чтения исходной таблицы, в копию не попадут.
- Запись можно остановить. Зафиксируйте паузу, выполните перенос и проверки, затем направьте приложение на новую таблицу.
- Запись должна продолжаться. Нужен механизм синхронизации изменений на время копирования — например, согласованная запись в оба места или репликация изменений. Это отдельная часть проекта: заранее определите, как обрабатывать повторные события и конфликты.
- Таблица слишком велика для одной вставки. Копируйте диапазонами по стабильному ключу и отмечайте завершённые порции. До запуска проверьте, что повтор порции не создаёт дубликаты и не затирает актуальные данные.
Не переключайте приложение, пока не определено, как оно переживёт откат. При прямом переносе можно вернуть таблицу в исходную схему обратным изменением. При копировании две таблицы могут разойтись по данным, поэтому возврат трафика на старую таблицу без обратной синхронизации способен потерять новые записи.
Что чаще всего ломается
Запросы находят не ту таблицу
В одной базе могут существовать таблицы с одинаковым именем в разных схемах. Явно задавайте схему в критичных запросах и настройках подключения. Проверьте значение search_path у пользователя приложения: это не замена контролю зависимостей, а порядок поиска объектов по неквалифицированному имени.
Права на таблицу есть, а доступа к схеме нет
Для обращения к объекту нужны подходящие права и на сам объект, и на схему. Проверьте доступ роли приложения к целевой схеме и таблице. Настройки прав по умолчанию не следует принимать за уже выданные права на существующую таблицу: убедитесь в фактическом доступе после переноса или копирования.
Число строк совпало, а данные — нет
Одинаковое количество записей не доказывает, что таблицы совпадают. Сверьте ключи, диапазоны дат и критичные суммы; для крупных таблиц выберите проверку по порциям. Если перенос шёл при активной записи, отдельно найдите изменения, появившиеся после старта копирования.
Откат возвращает имя, но не согласованность
Перемещение объекта и копирование — разные сценарии отката. При копировании не удаляйте источник сразу после переключения: сначала подтвердите работу приложения, проверьте фоновые процессы и согласуйте срок хранения старой таблицы. Если обе таблицы принимали записи, установите, какая из них считается источником истины.
Термин: схема — пространство имён внутри базы PostgreSQL. Полное имя объекта включает схему, например app.orders; сама схема не является отдельной базой данных.
Что сделать дальше
Перед миграцией на тестовой копии базы отработайте тот же сценарий и замерьте длительность, блокировки и объём создаваемого WAL. В день переключения следите за ошибками доступа, задержкой запросов и числом записей в старой и новой таблицах. После стабилизации удаляйте старые объекты только тогда, когда подтвердили, что приложение и задания больше к ним не обращаются.
Здесь разобран перенос таблиц внутри PostgreSQL 16. Перенос между разными базами, преобразование формата данных и настройка потоковой репликации требуют отдельного плана и своих проверок.
Проверка рекламы на риски: Что в макете вызовет вопросы ФАС: превосходные степени, сравнения, обещания результата, маркировка.
Спросить за 40 ₽Источники: PostgreSQL 16: Schemas, PostgreSQL 16: INSERT
Частые вопросы
Можно ли переместить таблицу в другую схему без копирования данных?
Что будет с внешними ключами и индексами при переносе таблицы?
Можно ли копировать данные, пока приложение продолжает запись?
Почему после копирования новых строк нарушается последовательность ID?
Будет ли миграция работать так же в другой версии PostgreSQL?
Нужно ли оставлять старую таблицу после переключения?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.