Wyłącz sprawdzanie kluczy obcych PostgreSQL dla migracji


92

Tworzę wiele migracji, które mają klucze obce w PostgreSQL 9.4.

Powoduje to ból głowy, ponieważ wszystkie tabele muszą być w dokładnie takiej kolejności, jakiej oczekują klucze obce podczas migracji. Robi się jeszcze trudniej, jeśli muszę uruchamiać migracje z innych pakietów, od których zależą moje nowe migracje dla klucza obcego.

W MySQL mogę to uprościć, dodając po prostu SET FOREIGN_KEY_CHECKS = 0;na początku mojego pliku migracji. Jak mogę to zrobić tymczasowo w PostgresSQL tylko na czas trwania kodu migracji?

BTW, używając do tego narzędzia Laravel Schema Builder.

Odpowiedzi:


83

PostgreSQL nie obsługuje żadnej opcji konfiguracyjnej, ale istnieje inna możliwość.

postgres=# \d b
        Table "public.b"
┌────────┬─────────┬───────────┐
│ Column │  Type   │ Modifiers │
╞════════╪═════════╪═══════════╡
│ id     │ integer │           │
└────────┴─────────┴───────────┘
Foreign-key constraints:
    "b_id_fkey" FOREIGN KEY (id) REFERENCES a(id) DEFERRABLE

Integralność referencyjna w Postgres jest implementowana przez wyzwalacze i możesz wyłączyć wyzwalacze w tabeli. Dzięki tej metodzie możesz przesłać dowolne dane (ryzyko), ale jest to znacznie szybsze - ponieważ sprawdzenie dużych danych jest kosztowne. A jeśli przesyłanie jest bezpieczne, możesz to zrobić.

BEGIN;
ALTER TABLE b DISABLE TRIGGER ALL;
-- now the RI over table b is disabled
ALTER TABLE b ENABLE TRIGGER ALL;
COMMIT;

Następną możliwością jest użycie odroczonych ograniczeń. To sprawdzenie ograniczenia ruchu, aby zatwierdzić czas. Dlatego nie należy szanować porządku przy INSERTpoleceniach:

ALTER TABLE b ALTER CONSTRAINT b_id_fkey DEFERRABLE;

BEGIN
postgres=# SET CONSTRAINTS b_id_fkey DEFERRED;
SET CONSTRAINTS
postgres=# INSERT INTO b VALUES(100); -- this is not in a table
INSERT 0 1
postgres=# INSERT INTO b VALUES(10);
INSERT 0 1 
postgres=# COMMIT;
ERROR:  insert or update on table "b" violates foreign key constraint "b_id_fkey"
DETAIL:  Key (id)=(100) is not present in table "a".

Ta metoda powinna być dla Ciebie preferowana, ponieważ wprowadzone dane zostaną sprawdzone.


2
Z jakiegoś powodu raz to zadziałało, a potem wcale. Jestem w aws aurora postgres, gdzie blokują super userrolę, aby klienci nie mogli zepsuć ustawień replikacji. Wygląda na to, że muszę być superużytkownikiem, aby wyłączyć niektóre wyzwalacze systemowe. (Obecnie używam mojego konta administratora, które jest również właścicielem - nie wiem, dlaczego to kiedyś zadziałało). Ustawienie opcji replikacji również nie jest realną opcją, ponieważ również wymaga super userroli. Wydaje mi się, że jedyną opcją jest upuszczenie i odtworzenie kluczy obcych ...
ps2goat

To samo tutaj. Robię DISABLE TRIGGER ALLcoś, ale nie ma to żadnego skutku. Nie dostaję nawet żadnego ostrzeżenia. To jest po prostu ignorowane.
jayarjo

Na Amazon RDS daje to następujący błąd:> odmowa pozwolenia: "RI_ConstraintTrigger_a_23031" jest wyzwalaczem systemowym, więc ten przepis nie jest niestety dla każdego przypadku :)
kolypto

Błąd w lokalnej bazie danych. Gdy użytkownik ma wszystkie uprawnienia do bazy danych, odmówiono ** uprawnień: „RI_ConstraintTrigger_a_16564” jest wyzwalaczem systemowym **
Solo.dmitry

154

W przypadku migracji łatwiej jest wyłączyć wszystkie wyzwalacze za pomocą:

SET session_replication_role = 'replica';

A po migracji wszystko można ponownie włączyć za pomocą

SET session_replication_role = 'origin';

3
Święta krowa, czy jest to zarówno prostsze, jak i bardziej odpowiednie do konkretnego zadania. (Tak.)
ijoseph

10
Uwaga: wymaga to uprawnień superużytkownika. Spróbuj „USTAW OGRANICZENIA WSZYSTKIE ODROCZONE”.
JJC,

9
Jestem włączony 10.4i powyższe stwierdzenie nie wydaje się działać.
Stephane

2
Czy ktoś byłby w stanie nakreślić zagrożenia / ryzyka związane z tą metodą, w jakich scenariuszach należy ją stosować i jak je ograniczać? Jaka jest najlepsza praktyka, jeśli zostanie to uznane za złą praktykę?
karns

6
Przy okazji, ten parametr można ustawić w AWS RDS w grupie parametrów bazy danych i zastosować bez restartowania db! Bardzo przydatne, jeśli używasz DMS w pustej bazie danych z istniejącym schematem i utworzonymi ograniczeniami.
Mike Atlas
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.