Saya telah mendapatkan dump database PostgreSQL saya dengan:
pg_dump -U user-name -d db-name -f dumpfile
yang kemudian saya lanjutkan untuk memulihkan di database lain dengan:
psql X -U postgres -d db-name-b -f dumpfile
Masalah saya adalah bahwa database berisi batasan referensi, pemeriksaan dan pemicu dan beberapa di antaranya (cek tampaknya akan khususnya) gagal selama restorasi karena informasi tidak dimuat dalam urutan yang akan menyebabkan pemeriksaan tersebut dihormati. Misalnya, memasukkan baris dalam tabel dapat dikaitkan dengan fungsi CHECK
panggilan plpgsql
yang memeriksa apakah suatu kondisi berlaku di beberapa tabel lain yang tidak terkait. Jika tabel terakhir itu tidak dimuat oleh psql
sebelum yang pertama, kesalahan terjadi.
Berikut ini adalah SSCCE yang menghasilkan database yang pernah dibuang pg_dump
tidak dapat dipulihkan:
CREATE OR REPLACE FUNCTION fail_if_b_empty () RETURNS BOOLEAN AS $$
SELECT EXISTS (SELECT 1 FROM b)
$$ LANGUAGE SQL;
CREATE TABLE IF NOT EXISTS a (
i INTEGER NOT NULL
);
INSERT INTO a(i) VALUES (0),(1);
CREATE TABLE IF NOT EXISTS b (
i INTEGER NOT NULL
);
INSERT INTO b(i) VALUES (0);
ALTER TABLE a ADD CONSTRAINT a_constr_1 CHECK (fail_if_b_empty());
Apakah ada cara untuk menonaktifkan (dari baris perintah) semua kendala seperti itu selama restorasi dump dan mengaktifkannya kembali setelah itu? Saya menjalankan PostgreSQL 9.1.
sumber
-X
dan-d
opsi untukpg_dump
.pg_dump
menghasilkan dump yang dapat disimpan dalam DB kosong.CHECK
batasan, maka semua jaminan dibatalkan, karena itu tidak didukung secara resmi, hanya ditoleransi. Tetapi menyatakanCHECK
kendalaNOT VALID
membuatnya bekerja untuk saya dalam segala hal. Mungkin ada kasing sudut yang tidak pernah saya sentuh ...Jawaban:
Jadi Anda mencari tabel lain di a
CHECK
batasan .CHECK
kendala seharusnya menjalankanIMMUTABLE
pemeriksaan. Apa yang lulus OK untuk satu baris sekaligus harus lulus OK setiap saat. BegitulahCHECK
batasan didefinisikan dalam standar SQL. Itu juga alasan pembatasan ini ( per dokumentasi ):Sekarang, ekspresi dalam
CHECK
batasan diizinkan untuk menggunakan fungsi, bahkan fungsi yang ditentukan pengguna. Itu harus dibatasi padaIMMUTABLE
fungsi, tetapi Postgres saat ini tidak memberlakukan ini. Menurut Ini diskusi terkait tentang peretas pgsql ini , salah satu alasannya adalah untuk memungkinkan referensi ke waktu saat ini, yangIMMUTABLE
pada dasarnya tidak.Tapi Anda mencari deretan meja lain, yang benar-benar melanggar cara
CHECK
seharusnya kendala bekerja. Saya tidak terkejut bahwapg_dump
gagal menyediakan ini.Pindahkan cek Anda di tabel lain ke a pemicu (yang merupakan alat yang tepat), dan seharusnya berfungsi dengan versi modern Postgres.
PostgreSQL 9.2 atau lebih baru
Sementara hal di atas berlaku untuk semua versi Postgres, beberapa alat telah diperkenalkan dengan Postgres 9.2 untuk membantu situasi Anda:
opsi pg_dump
--exclude-table-data
Solusi sederhana adalah membuang db tanpa data untuk tabel yang melanggar dengan:
Kemudian tambahkan hanya data untuk tabel ini di akhir dump dengan:
Tetapi komplikasi dengan kendala lain pada tabel yang sama mungkin terjadi. Ada solusi yang lebih baik lagi :
NOT VALID
Ada
NOT VALID
pengubah untuk kendala. Hanya tersedia untuk kendala FK di v9.1, tapi ini diperluas menjadiCHECK
kendala di 9.2. Per dokumentasi:File dump postgres polos terdiri dari tiga "bagian":
pre_data
data
post-data
Postgres 9.2 juga memperkenalkan opsi untuk membuang bagian secara terpisah
-- section=sectionname
, tetapi itu tidak membantu masalah yang ada.Di sinilah mulai menarik. Per dokumentasi:
Penekanan berani saya.
Anda dapat mengubah
CHECK
batasan yang menyinggungNOT VALID
, yang memindahkan kendala kepost-data
bagian. Jatuhkan dan buat ulang:Ini harus menyelesaikan masalah Anda. Anda bahkan dapat meninggalkan kendala dalam keadaan itu , karena itu lebih mencerminkan apa yang sebenarnya dilakukannya: memeriksa baris baru, tetapi tidak memberikan jaminan untuk data yang ada. Tidak ada yang salah dengan
NOT VALID
kendala pemeriksaan. Jika suka, Anda dapat memvalidasinya nanti:Tetapi kemudian Anda kembali ke status quo ante.
sumber
pg_dump
menambahkan pemicu di akhir file dump, sedangkan itu menciptakanCHECK
s sebagai bagian dariCREATE TABLE
perintah. Jadi restorasi bisa juga berhasil untuk kasus pemeriksaan jikapg_dump
alat menggunakan pendekatan yang berbeda. Saya gagal melihat mengapa DDL saya OK jika saya menggunakan pemicu tetapi tidak OK jika saya menggunakan pemeriksaan karena logika yang sama persis diterapkan dalam kedua kasus (Anda dapat melihat versi skrip menggunakan pemicu dalam jawaban saya sendiri).pg_dump
harus menghasilkan DDL berbeda untuk kendala pemeriksaan (misalnya menambahkan semuanya di akhir), Anda harus mempostingnya ke milis Postgres sebagai permintaan tambahan. Tapi saya setuju dengan Erwin bahwa Anda salah menggunakan batasan pemeriksaan untuk sesuatu yang tidak dirancang untuk mereka. Jadi saya tidak akan mengharapkan permintaan perubahan itu diterapkan dalam waktu dekat. Btw: SSCCE Anda akan dimodelkan lebih baik menggunakan kunci asing antara dua tabel.Tampaknya ini karena cara
pg_dump
membuat dump. Melihat dump aktual saya melihat bahwaCHECK
kendala hadir dalam file dump menggunakan sintaks yang merupakan bagian dariCREATE TABLE
perintah:Ini menciptakan kegagalan pada pemulihan database karena cek dilakukan sebelum tabel
a
atau tabelb
memiliki data di dalamnya. Namun jika, file dump diedit danCHECK
ditambahkan menggunakan sintaks berikut sebagai gantinya, di akhir file dump:... maka tidak ada masalah dalam restorasi.
Logika yang sama persis dapat diimplementasikan menggunakan
TRIGGER
seperti pada skrip berikut:Namun dalam kasus ini,
pg_dump
membuat (secara default) pemicu di akhir file dump (dan tidak dalamCREATE TABLE
pernyataan seperti dalam kasus cek) dan pemulihan berhasil.sumber