pg_restore: [archiwizator (db)] nie mógł wykonać zapytania: BŁĄD: schemat „public” już istnieje


18

Korzystam z pg_dump / pg_restore do tworzenia kopii zapasowych i przywracania bazy danych PostgreSQL, ale otrzymuję komunikaty o błędach (i niezerowy status wyjścia) z pg_restore. Wypróbowałem bardzo prostą skrzynkę podstawową (opisaną poniżej), ale nadal otrzymałem te błędy:

pg_restore: [archiwizator (db)] Błąd podczas PRZETWARZANIA Spisu treści:
pg_restore: [archiwizator (db)] Błąd z pozycji 5 spisu treści; 2615 2200 SCHEMA publiczne posty
pg_restore: [archiwizator (db)] nie mógł wykonać zapytania: BŁĄD: schemat „public” już istnieje
    Polecenie brzmiało: UTWÓRZ SCHEMAT publiczny;

Kroki ku reprodukcji:

  1. Zainstaluj świeżą, waniliową dystrybucję Ubuntu 14.04 (używam Vagrant z tym pudełkiem Vagrant ).
  2. Zainstaluj PostgreSQL 9.3, skonfiguruj, aby zezwalać na połączenia lokalne jako „postgres” użytkownika PostgreSQL od dowolnego użytkownika Linuksa.
  3. Utwórz testową bazę danych. Po prostu robię:

    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres postgres
    psql (9.3.5)
    Wpisz „help”, aby uzyskać pomoc.
    
    postgres = # stwórz bazę danych mydb;
    UTWÓRZ BAZA DANYCH
    postgres = # \ q
    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres mydb
    psql (9.3.5)
    Wpisz „help”, aby uzyskać pomoc.
    
    mydb = # utwórz dane tabeli (wpis bigint);
    UTWÓRZ TABELĘ
    mydb = # wstaw do wartości danych (1);
    WSTAW 0 1
    mydb = # wstaw do wartości danych (2);
    WSTAW 0 1
    mydb = # wstaw do wartości danych (3);
    WSTAW 0 1
    mydb = # \ q
    
  4. Utwórz kopię zapasową bazy danych w następujący sposób:

    PGPASSWORD = "postgres" pg_dump --dbname = mydb --username = postgres --format = custom> pg_backup.dump
  5. Usuń niektóre wiersze z tabeli danych na mydb, abyśmy mogli stwierdzić, czy dane zostały pomyślnie przywrócone.

  6. Przywróć bazę danych za pomocą:

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

Dane są przywracane, ale polecenie pg_restore w kroku 6 kończy działanie ze statusem 1i wyświetla następujące dane wyjściowe:

pg_restore: [archiwizator (db)] Błąd podczas PRZETWARZANIA Spisu treści:
pg_restore: [archiwizator (db)] Błąd z pozycji 5 spisu treści; 2615 2200 SCHEMA publiczne posty
pg_restore: [archiwizator (db)] nie mógł wykonać zapytania: BŁĄD: schemat „public” już istnieje
    Polecenie brzmiało: UTWÓRZ SCHEMAT publiczny;



OSTRZEŻENIE: błędy ignorowane podczas przywracania: 1

Nie mogę tego po prostu zignorować, ponieważ uruchamiam to polecenie programowo i muszę użyć statusu wyjścia, aby ustalić, czy odtwarzanie nie powiodło się. Początkowo zastanawiałem się, czy ten problem nie jest spowodowany tym, że umieściłem publicznie moją bazę danych (domyślny schemat). Uznałem, że publiczność zostanie utworzona w wyniku --createopcji przez pg_restore, zanim dane zostaną przywrócone (co może również próbować utworzyć ten schemat, ponieważ tam jest moja tabela), ale kiedy wypróbowałem powyższe kroki z moją tabelą w innym schemacie wyniki były takie same, a komunikaty o błędach były identyczne.

czy robię coś źle? Dlaczego widzę ten błąd?

Odpowiedzi:


16

Błąd jest nieszkodliwy, ale aby się go pozbyć, myślę, że musisz podzielić to przywracanie na dwa polecenia, jak w:

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

--cleanOpcja w pg_restore nie wygląda dużo, ale faktycznie podnosi nietrywialne problemy.

Dla wersji do 9.1

Kombinacja opcji --createi --cleanpg_restore była błędem w starszych wersjach PG (do 9.1). Rzeczywiście istnieje pewna sprzeczność między (cytowanie strony 9.1):

--clean Wyczyść (upuść) obiekty bazy danych przed ich odtworzeniem

i

--create Utwórz bazę danych przed jej przywróceniem.

Bo jaki jest sens czyszczenia w nowej bazie danych?

Począwszy od wersji 9.2

Kombinacja jest teraz akceptowana, a dokument mówi to (cytując stronę podręcznika 9.3):

--clean Wyczyść (upuść) obiekty bazy danych przed ich odtworzeniem. (Może to generować pewne nieszkodliwe komunikaty o błędach, jeśli w docelowej bazie danych nie będzie żadnych obiektów).

--create Utwórz bazę danych przed jej przywróceniem. Jeśli podano również opcję --clean, usuń i ponownie utwórz docelową bazę danych przed nawiązaniem z nią połączenia.

Teraz posiadanie obu razem prowadzi do tego rodzaju sekwencji podczas przywracania:

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

Nie ma DROPdla każdego pojedynczego obiektu, tylko DROP DATABASEna początku. Jeśli nie użyjesz, --createbyłoby odwrotnie.

W każdym razie ta sekwencja podnosi błąd publicschematu już istniejącego, ponieważ tworzenie mydbz template0już go zaimportowało (co jest normalne, jest to punkt bazy danych szablonów).

Nie jestem pewien, dlaczego ta sprawa nie jest obsługiwana automatycznie pg_restore. Może to spowodowałoby niepożądane skutki uboczne, gdy administrator zdecyduje się dostosować template0i / lub zmienić cel public, nawet jeśli nie powinniśmy tego robić.


Korzystam z wersji 9.6, a określenie --createbez cleannie rozwiązuje problemu.
Cerin

7

W moim przypadku powodem było to, że korzystałem pg_restorez wersji 11.2 postgresql-contrib do przywrócenia zrzutu wykonanego przez pg_dump9.6 do klastra PostgreSQL 9.6.

Po obniżeniu wersji z pg_restorepowrotem do 9.6 schema "public" already existsbłąd zniknął, a proces przywracania działał jak poprzednio.


Ale czy przywróciłeś zrzut przy użyciu pg_restore 9.6 do bazy danych postgres 11.2?
Mariano Ruiz

@MarianoRuiz Myślę, że moja pierwotna odpowiedź jest jasna: „Korzystałem z pg_restore z wersji 11.2 postgresql-contrib, aby przywrócić zrzut pg_dump 9.6 do klastra PostgreSQL 9.6”. Więc na twoje pytanie: Nie, nie zrobiłem tego. Mój pg_restore miał 11,2, podczas gdy pg klaster miał 9,6
Lu Liu
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.