pg_restore: [архіватор (db)] не зміг виконати запит: ПОМИЛКА: схема "public" вже існує


18

Я використовую pg_dump / pg_restore для резервного копіювання та відновлення бази даних PostgreSQL, але я отримую деякі повідомлення про помилки (і ненульовий статус виходу) з pg_restore. Я спробував надзвичайно простий базовий випадок (викладений нижче), але все-таки отримав ці помилки:

pg_restore: [архіватор (db)] Помилка під час обробки TOC:
pg_restore: [архіватор (db)] Помилка під час запису TOC 5; 2615 2200 SCHEMA public postgres
pg_restore: [архіватор (db)] не зміг виконати запит: ПОМИЛКА: схема "public" вже існує
    Командою були: СТВОРИТИ СХЕМУ громадські;

Кроки до відтворення:

  1. Встановіть свіжий ванільний дистрибутив Ubuntu 14.04 (я використовую Vagrant з цією коробкою Vagrant ).
  2. Встановіть PostgreSQL 9.3, налаштуйте так, щоб дозволити локальні з'єднання як "postgres" користувача PostgreSQL від будь-якого користувача Linux.
  3. Створіть тестову базу даних. Я просто роблю:

    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres postgres
    psql (9.3.5)
    Наберіть "довідка" для довідки.
    
    postgres = # створити базу даних mydb;
    СТВОРИТИ ДАНІ
    postgres = # \ q
    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres mydb
    psql (9.3.5)
    Наберіть "довідка" для довідки.
    
    mydb = # створити дані таблиці (вхід bigint);
    СТВОРИТИ СТІЛ
    mydb = # вставити у значення даних (1);
    ВСТАВКА 0 1
    mydb = # вставити у значення даних (2);
    ВСТАВКА 0 1
    mydb = # вставити у значення даних (3);
    ВСТАВКА 0 1
    mydb = # \ q
    
  4. Створіть резервну копію бази даних так:

    PGPASSWORD = "postgres" pg_dump --dbname = mydb --username = postgres --format = custom> pg_backup.dump
  5. Видаліть кілька рядків із таблиці даних у mydb, щоб ми змогли сказати, чи вдало відновили дані.

  6. Відновіть базу даних за допомогою:

    PGPASSWORD = "postgres" pg_restore --clean --create --dbname = postgres --username = postgres pg_backup.dump

Дані відновлюються, але команда pg_restore на етапі 6 виходить зі статусом 1та показує такий вихід:

pg_restore: [архіватор (db)] Помилка під час обробки TOC:
pg_restore: [архіватор (db)] Помилка під час запису TOC 5; 2615 2200 SCHEMA public postgres
pg_restore: [архіватор (db)] не зміг виконати запит: ПОМИЛКА: схема "public" вже існує
    Командою були: СТВОРИТИ СХЕМУ громадські;



ПОПЕРЕДЖЕННЯ: помилки ігноруються при відновленні: 1

Я не можу просто проігнорувати це, тому що я запускаю цю команду програмно і мені потрібно використовувати статус виходу, щоб визначити, не вдалося відновлення чи ні. Спочатку я замислювався, чи ця проблема не була, тому що я ставлю свою базу даних загальнодоступною (схема за замовчуванням). Я мотивував, що публікація буде створена в результаті --createопції за допомогою pg_restore до відновлення даних (що, можливо, можна спробувати створити і цю схему, оскільки саме там знаходиться моя таблиця), але коли я спробував вищевказані кроки зі своєю таблицею в іншій схемі результати були однаковими, а повідомлення про помилки були однаковими.

Я щось роблю не так? Чому я бачу цю помилку?

Відповіді:


16

Помилка нешкідлива, але для її усунення я думаю, що вам потрібно розбити це відновлення на дві команди, як у:

dropdb -U postgres mydb && \
 pg_restore --create --dbname=postgres --username=postgres pg_backup.dump

--cleanВаріант в pg_restore не виглядає як багато , але на самому справі викликає нетривіальні проблеми.

Для версій до 9.1

Комбінація параметрів --createі --cleanв параметрах pg_restore була помилкою у старих версіях PG (до 9.1). Дійсно є певне протиріччя (цитуючи сторінку 9.1):

- очистити (очистити) об’єкти бази даних перед їх відтворенням

і

--create Створити базу даних, перш ніж відновити її.

Тому що сенс очищення всередині нової бази даних?

Починаючи з версії 9.2

Тепер комбінація прийнята, і док говорить про це (цитуючи 9.3 вкладку):

- очистити (очистити) об’єкти бази даних перед їх відтворенням. (Це може створити кілька нешкідливих повідомлень про помилки, якщо жодних об’єктів не було в базі даних призначення.)

--create Створити базу даних, перш ніж відновити її. Якщо --clean також вказано, скиньте та відтворіть цільову базу даних перед підключенням до неї.

Тепер обидва разом ведуть до такої послідовності під час відновлення:

DROP DATABASE mydb;
...
CREATE DATABASE mydb WITH TEMPLATE = template0... [other options]
...
CREATE SCHEMA public;
...
CREATE TABLE...

Для DROPкожного окремого об'єкта немає, лише DROP DATABASEна початку. Якщо не використовувати --createце було б навпаки.

У будь-якому випадку ця послідовність викликає помилку publicвже існуючої схеми, оскільки створення mydbз template0імпортувало її вже (що нормально, це сенс бази даних шаблонів).

Я не впевнений, чому цей випадок не вирішується автоматично pg_restore. Можливо, це спричинить небажані побічні ефекти, коли адміністратор вирішить налаштувати template0та / або змінити призначення public, навіть якщо ми цього не повинні робити.


Я використовую 9.6, а вказівка --createбез cleanцього не виправляє проблему.
Серін

7

У моєму випадку причиною було те, що я використовував pg_restoreз postgresql-contrib версії 11.2, щоб відновити дамп, зроблений pg_dump9.6, на кластер PostgreSQL 9.6.

Після того як я знизив pg_restoreспину до рівня 9,6, ця schema "public" already existsпомилка зникла, і процес відновлення працював, як і раніше.


Але ви відновили дамп, використовуючи pg_restore 9.6 в базі даних postgres 11.2?
Маріано Руіс

@MarianoRuiz Я вважаю, що моя оригінальна відповідь зрозуміла: "Я використовував pg_restore з postgresql-contrib версії 11.2, щоб відновити дамп, зроблений pg_dump 9.6, на кластер PostgreSQL 9.6." Отже, до вашого запитання: Ні, я цього не зробив. Мій pg_restore був 11,2, тоді як кластер pg - 9,6
Lu Liu
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.