pg_restore: [pengarsip (db)] tidak dapat mengeksekusi query: ERROR: skema "public" sudah ada
Saya menggunakan pg_dump / pg_restore untuk mencadangkan dan memulihkan basis data PostgreSQL, tetapi saya mendapatkan beberapa pesan kesalahan (dan status keluar bukan nol) dari pg_restore. Saya mencoba kasus dasar yang sangat sederhana (diuraikan di bawah ini) tetapi masih mendapatkan kesalahan ini:
pg_restore: [archiver (db)] Kesalahan saat MEMPROCESSING TOC: pg_restore: [archiver (db)] Kesalahan dari entri TOC 5; 2615 2200 SCHEMA public postgres pg_restore: [archiver (db)] tidak dapat mengeksekusi query: ERROR: skema "public" sudah ada Perintahnya adalah: CREATE SCHEMA public;
Langkah-langkah untuk mereproduksi:
-
Instal distro Ubuntu 14.04 vanilla yang baru (saya menggunakan Vagrant dengan kotak Vagrant ini).
-
Instal PostgreSQL 9.3, konfigurasikan untuk mengizinkan koneksi lokal sebagai pengguna PostgreSQL "postgres &" dari pengguna Linux mana pun.
-
Buatlah sebuah test database. Saya baru saja melakukannya:
vagrant@vagrant-ubuntu-trusty-64:~$ psql --username=postgres postgres psql (9.3.5) Ketik "help" untuk bantuan.
postgres=# create database mydb; MEMBUAT BASIS DATA postgres=# \q vagrant@vagrant-ubuntu-trusty-64:~$ psql --username=postgres mydb psql (9.3.5) Ketik "help" untuk bantuan.
mydb=# membuat tabel data(entri bigint); CREATE TABLE mydb=# masukkan ke dalam data values(1); INSERT 0 1 mydb=# masukkan ke dalam data values(2); INSERT 0 1 mydb=# masukkan ke dalam data values(3); INSERT 0 1 mydb=# \q
-
Buat backup database seperti ini:
PGPASSWORD="postgres" pg_dump --dbname=mydb --username=postgres --format=custom > pg_backup.dump
-
Hapus beberapa baris dari tabel data di mydb sehingga kita akan dapat mengetahui apakah kita berhasil memulihkan data.
-
Kembalikan database dengan:
PGPASSWORD="postgres" pg_restore --clean --create --dbname=postgres --username=postgres pg_backup.dump
Data dipulihkan, tetapi perintah pg_restore pada langkah 6 keluar dengan status 1
dan menunjukkan output berikut:
pg_restore: [archiver (db)] Kesalahan saat MEMPROCESSING TOC: pg_restore: [archiver (db)] Kesalahan dari entri TOC 5; 2615 2200 SCHEMA public postgres pg_restore: [archiver (db)] tidak dapat mengeksekusi query: ERROR: skema "public" sudah ada Perintahnya adalah: CREATE SCHEMA public;PERINGATAN: kesalahan diabaikan saat pemulihan: 1
Saya tidak bisa mengabaikan ini karena saya menjalankan perintah ini secara terprogram dan perlu menggunakan status keluar untuk menentukan apakah restore gagal atau tidak. Awalnya, saya bertanya-tanya apakah masalah ini disebabkan karena saya meletakkan database saya di public (skema default). Saya beralasan bahwa publik akan dibuat sebagai hasil dari opsi --create
oleh pg_restore sebelum data direstore (yang bisa dibayangkan akan mencoba membuat skema itu juga karena di situlah tabel saya berada), tetapi ketika saya mencoba langkah-langkah di atas dengan tabel saya dalam skema yang berbeda, hasilnya sama dan pesan errornya identik.
Apakah saya melakukan sesuatu yang salah? Mengapa saya melihat kesalahan ini?
Kesalahan ini tidak berbahaya tetapi untuk menghilangkannya, saya pikir Anda perlu memecah pemulihan ini menjadi dua perintah, seperti pada:
Opsi
-bersih
di pg_restore tidak terlihat banyak tetapi sebenarnya menimbulkan masalah yang tidak sepele.Untuk versi hingga 9.1
Kombinasi opsi
--create
dan--clean
di pg_restore dulu merupakan kesalahan di versi PG yang lebih lama (hingga 9.1). Memang ada beberapa kontradiksi antara (mengutip manpage 9.1):dan
Karena apa gunanya membersihkan di dalam database baru?
Mulai dari versi 9.2
Kombinasi ini sekarang diterima dan dokumen mengatakan ini (mengutip manpage 9.3):
Sekarang dengan memiliki keduanya bersama-sama akan menghasilkan urutan seperti ini selama pemulihan Anda:
Tidak ada
DROP
untuk setiap objek individu, hanyaDROP DATABASE
di awal. Jika tidak menggunakan--create
ini akan menjadi kebalikannya.Bagaimanapun juga urutan ini menimbulkan kesalahan skema
public
sudah ada karena membuatmydb
daritemplate0
telah mengimpornya (yang mana ini normal, ini adalah inti dari database template).Saya tidak yakin mengapa kasus ini tidak ditangani secara otomatis oleh
pg_restore
. Mungkin hal ini akan menyebabkan efek samping yang tidak diinginkan ketika admin memutuskan untuk mengkustomisasitemplate0
dan/atau mengubah tujuanpublic
, bahkan jika kita tidak seharusnya melakukan itu.Dalam kasus saya, alasannya adalah saya menggunakan
pg_restore
dari postgresql-contrib versi 11.2 untuk mengembalikan dump yang dibuat olehpg_dump
9.6 ke klaster PostgreSQL 9.6.Setelah saya menurunkan
pg_restore
saya kembali ke 9.6, kesalahanschema "public" already exists
ini hilang, dan proses pemulihan bekerja seperti sebelumnya.