마이그레이션을위한 PostgreSQL 외래 키 검사 비활성화


83

PostgreSQL 9.4에서 외래 키가있는 마이그레이션을 많이 만들고 있습니다.

테이블이 모두 마이그레이션 될 때 외래 키가 예상하는 정확한 순서를 따라야하기 때문에 골치 아픈 일입니다. 내 새 마이그레이션이 외래 키에 의존하는 다른 패키지에서 마이그레이션을 실행해야하는 경우 더욱 끈적 거립니다.

MySQL에서는 SET FOREIGN_KEY_CHECKS = 0;마이그레이션 파일의 맨 위에 간단히 추가 하여 이를 단순화 할 수 있습니다 . 마이그레이션 코드 길이에 대해서만 PostgresSQL에서 임시로이 작업을 수행하려면 어떻게해야합니까?

BTW,이를 위해 Laravel Schema Builder를 사용합니다.

답변:


76

PostgreSQL은 구성 옵션을 지원하지 않지만 다른 가능성이 있습니다.

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

Postgres의 참조 무결성은 트리거로 구현되며 테이블에서 트리거를 비활성화 할 수 있습니다. 이 방법을 사용하면 모든 데이터 (위험)를 업로드 할 수 있지만 대용량 데이터를 검사하는 데 비용이 많이 들기 때문에 훨씬 더 빠릅니다. 업로드가 안전하다면 할 수 있습니다.

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

다음 가능성은 지연된 제약을 사용하는 것입니다. 이 이동 제약 검사는 시간을 커밋합니다. 따라서 INSERT명령으로 질서를 존중해서는 안됩니다 .

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".

삽입 된 데이터를 확인하므로이 방법이 선호됩니다.


2
어떤 이유로, 이것은 나를 위해 한 번 작동했지만 전혀 작동하지 않았습니다. 저는 super user고객이 복제 설정을 엉망으로 만들지 못하도록 역할 을 잠그는 aws aurora postgres에 있습니다. 일부 시스템 트리거를 비활성화하려면 슈퍼 유저 여야하는 것 같습니다. (현재 소유자이기도 한 내 관리자 계정을 사용하고 있습니다. 한 번 작동 한 이유를 잘 모르겠습니다.) 복제 옵션을 설정하는 것도 super user역할이 필요하기 때문에 실행 가능한 옵션이 아닙니다 . 내 유일한 옵션은 ... 삭제하고 외부 키를 다시 할 것 같다
ps2goat

여기도 마찬가지입니다. 이렇게 DISABLE TRIGGER ALL일을하지만 아무 효과가 없습니다. 나는 경고조차받지 않는다. 그냥 무시됩니다.
jayarjo

Amazon RDS에서 다음 오류가 발생합니다.> permission denied : "RI_ConstraintTrigger_a_23031"은 시스템 트리거이므로이 레시피는 모든 경우에 적용되지 않습니다. :)
kolypto

147

마이그레이션의 경우 다음을 사용하여 모든 트리거를 비활성화하는 것이 더 쉽습니다.

SET session_replication_role = 'replica';

마이그레이션 후

SET session_replication_role = 'origin';

2
이런 소, 이것은 당면한 특정 작업에 더 간단하고 더 적합합니다. (예)
ijoseph

8
주의 사항 : 수퍼 유저 권한이 필요합니다. "SET CONSTRAINTS ALL DEFERRED"를 시도하십시오.
JJC

8
나는 켜져 10.4있고 위의 진술이 작동하지 않는 것 같습니다.
Stephane

2
누군가가이 방법의 위험 / 위험을 설명하고 어떤 시나리오에서 사용해야하며 위험을 완화하는 방법을 설명 할 수 있습니까? 이것이 좋지 않은 관행으로 간주되는 경우 모범 사례는 무엇입니까?
karns

6
Btw,이 파라미터는 데이터베이스 파라미터 그룹의 AWS RDS에서 설정하고 db를 다시 시작하지 않고도 적용 할 수 있습니다! 기존 스키마 및 제약 조건이 생성 된 빈 db에 DMS를 사용하는 경우 매우 유용합니다.
Mike Atlas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.