| nesterov |
| Junior |
Сообщения: 45 |
Репутация: 34 |
| Дата регистрации: |
| 08.08.2026 |
АВТОР ТЕМЫ31 окт. 2026 г., 17:00 (GMT+3)
Переносил небольшую базу на чистый сервер. Это учёт для знакомой мастерской: заказы, клиенты, пара справочников. Postgres, одна база, одно приложение, которое ходит в неё под своим пользователем. Резервные копии делались каждую ночь через pg_dump в custom-формате и уезжали на другую машину. Пробное восстановление когда-то тоже делали. Казалось, переезд займёт полчаса.
На новом сервере поставил ту же мажорную версию, создал пустую базу и запустил восстановление:
Полетели строки. Сначала ошибки про владельца: роль такая-то не существует. Потом про GRANT. В конце pg_restore сообщил, что ошибки были, но он их проигнорировал. Таблицы на месте, количество строк сходится с тем, что я записал перед переносом. Формально данные восстановлены.
Приложение при этом не запустилось. Его пользователя на новом сервере просто не было, а все объекты в базе теперь принадлежали postgres, потому что владельца назначить было некому.
Причина простая, и о ней почему-то вспоминают при первом переезде, а не при настройке копий. pg_dump сохраняет одну базу: схему, данные, права на объекты внутри неё. Роли и их пароли к конкретной базе не относятся, они общие для всего кластера. В дамп одной базы они не попадают. Тестовое восстановление когда-то прошло без вопросов, потому что делалось на том же сервере, где все роли уже были.
Выхода два, и они для разных случаев.
Первый — сохранять глобальные объекты отдельно:
Там роли, их атрибуты, членство в группах, табличные пространства. Нужны права суперпользователя. Восстанавливается этот файл до pg_restore, тогда владельцы и права встают на свои места. Одно предупреждение: в файле лежат хэши паролей ролей. Это не открытый текст, но и не то, что можно хранить рядом с дампом в общей папке. Обращаться с ним стоит как с секретом.
Второй — сознательно отказаться от исходных владельцев:
Так объекты достанутся указанной роли, а права потом выдаются заново. Это удобно, когда переносишь базу в другое окружение, где роли и так другие. Но надо понимать, что исходная схема прав теряется. Если в базе было несколько ролей с разным доступом, придётся вспоминать, кому что выдавали.
Я в тот раз пошёл вторым путём: роль одна, восстановить её руками несложно. Потом добавил выгрузку globals в ночное задание и отдельно переписал проверку копии. Раньше проверка была такой: файл есть, размер разумный, pg_restore --list читает оглавление. Это подтверждает, что дамп не битый. Это не подтверждает, что из него можно поднять работающую систему на чистой машине.
Ещё пара мест, которые на чистом сервере могут вести себя иначе, чем на старом. Я их не встретил, но проверяю. Расширения: дамп содержит CREATE EXTENSION, а пакет расширения на новом сервере должен быть установлен. Локаль и правила сортировки базы: если на новой системе другая библиотека сортировки, порядок строк и индексы по тексту могут вести себя не так, как вы привыкли. Про это у Postgres есть отдельные предупреждения в документации, лучше прочитать до переноса, а не после.
В итоге для себя я перестал считать копией один файл дампа. Копия — это дамп, globals, записка с версией Postgres и списком расширений, и одна проверка на машине, где нет ничего от старого сервера.
Кому интересно сравнить: как вы храните глобальные объекты? Отдельным файлом рядом с дампом, в менеджере секретов, или роли у вас описаны в коде развёртывания и из копий их сознательно исключают? Последний вариант мне кажется чище, но я его ни разу не доводил до конца на маленьком проекте, где всё держится на одном человеке.
На новом сервере поставил ту же мажорную версию, создал пустую базу и запустил восстановление:
pg_restore -d имя_базы /путь/к/дампу.dump
Полетели строки. Сначала ошибки про владельца: роль такая-то не существует. Потом про GRANT. В конце pg_restore сообщил, что ошибки были, но он их проигнорировал. Таблицы на месте, количество строк сходится с тем, что я записал перед переносом. Формально данные восстановлены.
Приложение при этом не запустилось. Его пользователя на новом сервере просто не было, а все объекты в базе теперь принадлежали postgres, потому что владельца назначить было некому.
Причина простая, и о ней почему-то вспоминают при первом переезде, а не при настройке копий. pg_dump сохраняет одну базу: схему, данные, права на объекты внутри неё. Роли и их пароли к конкретной базе не относятся, они общие для всего кластера. В дамп одной базы они не попадают. Тестовое восстановление когда-то прошло без вопросов, потому что делалось на том же сервере, где все роли уже были.
Выхода два, и они для разных случаев.
Первый — сохранять глобальные объекты отдельно:
pg_dumpall --globals-only > globals.sql
Там роли, их атрибуты, членство в группах, табличные пространства. Нужны права суперпользователя. Восстанавливается этот файл до pg_restore, тогда владельцы и права встают на свои места. Одно предупреждение: в файле лежат хэши паролей ролей. Это не открытый текст, но и не то, что можно хранить рядом с дампом в общей папке. Обращаться с ним стоит как с секретом.
Второй — сознательно отказаться от исходных владельцев:
pg_restore --no-owner --no-privileges --role=новая_роль -d имя_базы дамп.dump
Так объекты достанутся указанной роли, а права потом выдаются заново. Это удобно, когда переносишь базу в другое окружение, где роли и так другие. Но надо понимать, что исходная схема прав теряется. Если в базе было несколько ролей с разным доступом, придётся вспоминать, кому что выдавали.
Я в тот раз пошёл вторым путём: роль одна, восстановить её руками несложно. Потом добавил выгрузку globals в ночное задание и отдельно переписал проверку копии. Раньше проверка была такой: файл есть, размер разумный, pg_restore --list читает оглавление. Это подтверждает, что дамп не битый. Это не подтверждает, что из него можно поднять работающую систему на чистой машине.
Ещё пара мест, которые на чистом сервере могут вести себя иначе, чем на старом. Я их не встретил, но проверяю. Расширения: дамп содержит CREATE EXTENSION, а пакет расширения на новом сервере должен быть установлен. Локаль и правила сортировки базы: если на новой системе другая библиотека сортировки, порядок строк и индексы по тексту могут вести себя не так, как вы привыкли. Про это у Postgres есть отдельные предупреждения в документации, лучше прочитать до переноса, а не после.
В итоге для себя я перестал считать копией один файл дампа. Копия — это дамп, globals, записка с версией Postgres и списком расширений, и одна проверка на машине, где нет ничего от старого сервера.
Кому интересно сравнить: как вы храните глобальные объекты? Отдельным файлом рядом с дампом, в менеджере секретов, или роли у вас описаны в коде развёртывания и из копий их сознательно исключают? Последний вариант мне кажется чище, но я его ни разу не доводил до конца на маленьком проекте, где всё держится на одном человеке.
0