Otrzymałem zrzut mojej bazy danych PostgreSQL z:
pg_dump -U user-name -d db-name -f dumpfile
którą następnie przywracam w innej bazie danych za pomocą:
psql X -U postgres -d db-name-b -f dumpfile
Mój problem polega na tym, że baza danych zawiera ograniczenia referencyjne, kontrole i wyzwalacze, a niektóre z nich (kontrole, jak by się to wydawało w szczególności) zawodzą podczas przywracania, ponieważ informacje nie są ładowane w kolejności, która spowodowałaby, że kontrole te zostałyby uznane. Na przykład wstawienie wiersza w tabeli może być powiązane z funkcją CHECK
wywołującą plpgsql
funkcję, która sprawdza, czy warunek zachowuje się w innej niepowiązanej tabeli. Jeśli ta ostatnia tabela nie zostanie załadowana psql
przed pierwszą, pojawi się błąd.
Poniżej przedstawiono kod SSCCE, który tworzy bazę danych, której pg_dump
nie można przywrócić po zrzuceniu :
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());
Czy istnieje sposób, aby wyłączyć (z wiersza poleceń) wszystkie takie ograniczenia podczas przywracania zrzutu i włączyć je ponownie później? Korzystam z PostgreSQL 9.1.
źródło
-X
i-d
opcjipg_dump
.pg_dump
tworzy zrzut, który można odtworzyć w pustej bazie danych.CHECK
ograniczeniu, wówczas wszystkie gwarancje zostaną unieważnione, ponieważ nie jest to oficjalnie obsługiwane, tylko tolerowane. Ale stwierdzenieCHECK
ograniczeniaNOT VALID
sprawiło, że zadziałało to dla mnie pod każdym względem. Mogą istnieć przypadki narożne, których nigdy nie dotknąłem ...Odpowiedzi:
Więc przeglądasz inne tabele z
CHECK
ograniczeniem .CHECK
ograniczenia powinny uruchamiaćIMMUTABLE
kontrole. To, co przechodzi OK dla wiersza w jednym czasie, powinno przejść OK w dowolnym momencie. TakCHECK
definiowane są ograniczenia w standardzie SQL. To jest również powód tego ograniczenia ( według dokumentacji ):Teraz wyrażenia w
CHECK
ograniczeniach mogą używać funkcji, nawet funkcji zdefiniowanych przez użytkownika. Powinny one być ograniczone doIMMUTABLE
funkcji, ale Postgres obecnie tego nie egzekwuje. Zgodnie z tą pokrewną dyskusją na temat hakerów pgsql , jednym z powodów jest zezwolenie na odniesienia do aktualnego czasu, który nie jestIMMUTABLE
z natury.Ale patrzysz na rzędy innego stołu, co całkowicie narusza to, jak
CHECK
powinny działać ograniczenia. Nie dziwię się, że topg_dump
nie zapewnia.Przenieś swój czek w innej tabeli do wyzwalacza (który jest właściwym narzędziem) i powinien on działać z nowoczesnymi wersjami Postgres.
PostgreSQL 9.2 lub nowszy
Chociaż powyższe dotyczy wszystkich wersji Postgres, w Postgres 9.2 wprowadzono kilka narzędzi, które mogą pomóc w twojej sytuacji:
opcja pg_dump
--exclude-table-data
Prostym rozwiązaniem byłoby zrzucenie bazy danych bez danych dla tabeli naruszającej:
Następnie dołącz tylko dane dla tej tabeli na końcu zrzutu za pomocą:
Ale mogą wystąpić komplikacje z innymi ograniczeniami na tym samym stole. Istnieje jeszcze lepsze rozwiązanie :
NOT VALID
Istnieje
NOT VALID
modyfikator ograniczeń. Dostępne tylko dla ograniczenia FK w wersji 9.1, ale zostało rozszerzone naCHECK
ograniczenia w wersji 9.2. Według dokumentacji:Zwykły plik zrzutu postgres składa się z trzech „sekcji”:
pre_data
data
post-data
Postgres 9.2 wprowadził także opcję osobnego zrzutu sekcji
-- section=sectionname
, ale to nie pomaga w rozwiązaniu problemu.Tutaj jest ciekawie. Według dokumentacji:
Odważny nacisk mój.
Możesz zmienić obraźliwe
CHECK
ograniczenie naNOT VALID
, które przenosi ograniczenie dopost-data
sekcji. Upuść i utwórz ponownie:To powinno rozwiązać twój problem. Możesz nawet pozostawić ograniczenie w tym stanie , ponieważ lepiej odzwierciedla to, co faktycznie robi: sprawdź nowe wiersze, ale nie daje żadnych gwarancji dla istniejących danych. Nie ma nic złego w
NOT VALID
ograniczeniu sprawdzania. Jeśli wolisz, możesz to sprawdzić później:Ale potem wracasz do status quo ante.
źródło
pg_dump
dodaje wyzwalacze na końcu pliku zrzutu, podczas gdy tworzyCHECK
s jako częśćCREATE TABLE
polecenia. Przywrócenie mogłoby się również powieść w przypadku sprawdzania, gdybypg_dump
narzędzie zastosowało inne podejście. Nie rozumiem, dlaczego mój DDL jest OK, jeśli używam wyzwalaczy, ale nie OK, jeśli używam sprawdzeń, ponieważ w obu przypadkach zaimplementowana jest ta sama logika (wersję skryptu można zobaczyć we własnej odpowiedzi).pg_dump
powinieneś wygenerować inny DDL dla ograniczeń sprawdzania (np. Dodając je wszystkie na końcu), powinieneś opublikować to na liście mailingowej Postgres jako prośbę o ulepszenie. Ale zgadzam się z Erwinem, że niewłaściwie używasz ograniczeń kontrolnych do czegoś, do czego nie zostały zaprojektowane. Więc nie spodziewałbym się, że to żądanie zmiany zostanie wprowadzone w najbliższej przyszłości. Btw: Twój SSCCE byłby lepiej modelowany przy użyciu klucza obcego między dwiema tabelami.Wydaje się, że wynika to ze sposobu, w jaki
pg_dump
tworzy zrzut. Patrząc na zrzut, zauważyłem, żeCHECK
ograniczenie było obecne w pliku zrzutu, używając składni, która jest częściąCREATE TABLE
polecenia:Powoduje to awarię po przywróceniu bazy danych, ponieważ sprawdzanie jest przeprowadzane, zanim tabela
a
lub tabela będąb
miały w sobie jakiekolwiek dane. Jeśli jednak plik zrzutu jest edytowany iCHECK
dodawany jest przy użyciu następującej składni zamiast tego na końcu pliku zrzutu:... to nie ma problemu z przywróceniem.
Dokładną tę samą logikę można zaimplementować za pomocą polecenia
TRIGGER
jak w następującym skrypcie:W tym przypadku jednak
pg_dump
tworzy (domyślnie) wyzwalacz na końcu pliku zrzutu (a nie wCREATE TABLE
instrukcji, jak w przypadku sprawdzania), więc przywracanie powiodło się.źródło