pg_restore: [archiver (db)] tidak dapat menjalankan query: ERROR: schema “public” sudah ada

17

Saya menggunakan pg_dump / pg_restore untuk mem-backup dan mengembalikan database PostgreSQL, tetapi saya mendapatkan beberapa pesan kesalahan (dan status keluar yang tidak nol) dari pg_restore. Saya mencoba kasus dasar super sederhana (diuraikan di bawah) tetapi masih mendapat kesalahan ini:

pg_restore: [archiver (db)] Kesalahan saat MEMPROSES TOC:
pg_restore: [archiver (db)] Kesalahan dari entri TOC 5; 2615 2200 SCHEMA postgres publik
pg_restore: [archiver (db)] tidak dapat menjalankan query: ERROR: schema "public" sudah ada
    Perintah adalah: CREATE SCHEMA public;

Langkah-langkah mereproduksi:

  1. Instal distro vanilla Ubuntu 14.04 yang baru (saya menggunakan Vagrant dengan kotak Vagrant ini ).
  2. Instal PostgreSQL 9.3, konfigurasikan untuk memungkinkan koneksi lokal sebagai "postgres" pengguna PostgreSQL dari setiap pengguna Linux.
  3. Buat database uji. Saya hanya melakukan:

    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres postgres
    psql (9.3.5)
    Ketik "bantuan" untuk bantuan.
    
    postgres = # buat database mydb;
    BUAT DATABASE
    postgres = # \ q
    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres mydb
    psql (9.3.5)
    Ketik "bantuan" untuk bantuan.
    
    mydb = # buat data tabel (entri bigint);
    BUAT TABEL
    mydb = # masukkan ke dalam nilai data (1);
    INSERT 0 1
    mydb = # masukkan ke dalam nilai data (2);
    INSERT 0 1
    mydb = # masukkan ke dalam nilai data (3);
    INSERT 0 1
    mydb = # \ q
    
  4. Buat cadangan dari database seperti:

    PGPASSWORD = "postgres" pg_dump --dbname = mydb --username = postgres --format = custom> pg_backup.dump
  5. Hapus beberapa baris dari tabel data di mydb sehingga kami dapat mengetahui apakah kami berhasil memulihkan data.

  6. Pulihkan database dengan:

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

Data dipulihkan, tetapi perintah pg_restore di langkah 6 keluar dengan status 1dan menampilkan output berikut:

pg_restore: [archiver (db)] Kesalahan saat MEMPROSES TOC:
pg_restore: [archiver (db)] Kesalahan dari entri TOC 5; 2615 2200 SCHEMA postgres publik
pg_restore: [archiver (db)] tidak dapat menjalankan query: ERROR: schema "public" sudah ada
    Perintah adalah: CREATE SCHEMA public;



PERINGATAN: kesalahan diabaikan pada pemulihan: 1

Saya tidak bisa mengabaikan ini karena saya menjalankan perintah ini secara terprogram dan perlu menggunakan status keluar untuk menentukan apakah pemulihan gagal atau tidak. Awalnya, saya bertanya-tanya apakah masalah ini karena saya meletakkan database saya di depan umum (skema default). Saya beralasan bahwa publik akan dibuat sebagai hasil dari --createopsi oleh pg_restore sebelum data dipulihkan (yang mungkin bisa mencoba membuat skema itu juga karena di situlah meja saya berada), tetapi ketika saya mencoba langkah-langkah di atas dengan meja saya dalam skema yang berbeda, hasilnya sama dan pesan kesalahannya sama.

Apakah saya melakukan sesuatu yang salah? Mengapa saya melihat kesalahan ini?

KSletmoe
sumber

Jawaban:

16

Kesalahan tidak berbahaya tetapi untuk menghilangkannya, saya pikir Anda perlu memecah pemulihan ini menjadi dua perintah, seperti pada:

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

The --cleanpilihan di pg_restore tidak tampak seperti banyak tapi benar-benar menimbulkan masalah non-sepele.

Untuk versi hingga 9.1

Kombinasi opsi --createdan --cleandi pg_restore digunakan untuk menjadi kesalahan dalam versi PG yang lebih lama (hingga 9,1). Memang ada beberapa kontradiksi di antara (mengutip halaman manual 9.1):

--clean Clean (drop) objek database sebelum membuatnya kembali

dan

--create Buat database sebelum mengembalikan ke dalamnya.

Karena apa gunanya membersihkan di dalam basis data baru?

Mulai dari versi 9.2

Kombinasi tersebut sekarang diterima dan dokter mengatakan ini (mengutip halaman manual 9.3):

--clean Clean (drop) objek database sebelum membuatnya kembali. (Ini mungkin menghasilkan beberapa pesan kesalahan yang tidak berbahaya, jika ada objek yang tidak ada di database tujuan.)

--create Buat database sebelum mengembalikan ke dalamnya. Jika --clean juga ditentukan, jatuhkan dan buat kembali basis data target sebelum menghubungkannya.

Sekarang memiliki keduanya bersama-sama mengarah ke urutan seperti ini selama pemulihan Anda:

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

Tidak ada DROPuntuk setiap objek individu, hanya a DROP DATABASEdi awal. Jika tidak menggunakan --createini akan menjadi kebalikannya.

Pokoknya urutan ini menimbulkan kesalahan publicskema yang sudah ada karena membuat mydbdari template0telah mengimpornya (yang normal, itu adalah inti dari database templat).

Saya tidak yakin mengapa kasus ini tidak ditangani secara otomatis oleh pg_restore. Mungkin ini akan menyebabkan efek samping yang tidak diinginkan ketika admin memutuskan untuk menyesuaikan template0dan / atau mengubah tujuan public, bahkan jika kita tidak seharusnya melakukan itu.

Daniel Vérité
sumber
Saya menggunakan 9.6, dan menspesifikasikan --createtanpa cleantidak memperbaiki masalah.
Cerin
6

Dalam kasus saya, alasannya adalah bahwa saya menggunakan pg_restoredari postgresql-contrib versi 11.2 untuk mengembalikan dump yang dibuat oleh pg_dump9.6 ke cluster PostgreSQL 9.6.

Setelah saya menurunkan pg_restorepunggung saya menjadi 9,6, schema "public" already existskesalahan ini hilang, dan proses pemulihan bekerja seperti sebelumnya.

Lu Liu
sumber
Tetapi apakah Anda mengembalikan dump menggunakan pg_restore 9.6 ke dalam database postgres 11.2?
Mariano Ruiz
@MarianoRuiz Saya pikir jawaban asli saya jelas: "Saya menggunakan pg_restore dari postgresql-contrib versi 11.2 untuk mengembalikan dump yang dibuat oleh pg_dump 9.6 ke cluster PostgreSQL 9.6." Jadi untuk pertanyaan Anda: Tidak, saya tidak. Pg_restore saya 11,2 sedangkan cluster pg 9,6
Lu Liu