Jak tymczasowo wyłączyć wyzwalacze w PostgreSQL?


140

Ładuję dane zbiorczo i mogę ponownie obliczyć wszystkie modyfikacje wyzwalacza znacznie taniej po fakcie niż na podstawie wiersza po wierszu.

Jak mogę tymczasowo wyłączyć wszystkie wyzwalacze w PostgreSQL?

Odpowiedzi:


173

Alternatywnie, jeśli chcesz wyłączyć wszystkie wyzwalacze, a nie tylko te z tabeli USER, możesz użyć:

SET session_replication_role = replica;

Spowoduje to wyłączenie wyzwalaczy dla bieżącej sesji.

Aby ponownie włączyć dla tej samej sesji:

SET session_replication_role = DEFAULT;

Źródło: http://koo.fi/blog/2013/01/08/disable-postgresql-triggers-temporary/


2
Niesamowite. Zrobiłem moje masowe usuwanie z 30 minut do <1 sekundy :)
— Dan Lenski


2
Ostatnie pół godziny spędziłem na próżno szukając sposobu na obejście błędu „narusza ograniczenia klucza obcego” w moim środowisku testowym i to jest dokładnie to!
— Amalgovinus

Jedno zastrzeżenie: zgodnie z dokumentacją konfiguracyjną środowiska uruchomieniowego i dokumentacją ALTER TABLE będzie to działać z normalnymi wyzwalaczami, ale nie z tymi ustawionymi za pomocą ENABLE REPLICAlub ENABLE ALWAYS.
— beldaz

Jestem włączony 10.4i wydaje się, że ignoruję powyższe stwierdzenie.
— Stephane

131

PostgreSQL zna ALTER TABLE tblname DISABLE TRIGGER USERpolecenie, które wydaje się robić to, czego potrzebuję. Zobacz ALTER TABLE .


A w jaki sposób „przeliczysz wszystkie modyfikacje wyzwalacza”?
— Wojtek Kruszewski

15
Ostrożnie z jednoczesnym obciążeniem: ALTER TABLE ... DISABLE TRIGGER USERwymaga wyłącznej blokady na stole.
— Erwin Brandstetter

3
@WojtekKruszewski, myślę, że Dawid miał na myśli, że może przeliczyć zmiany ręcznie, które zrobiłby wyzwalacz, korzystając z wcześniejszej wiedzy (na przykład, jeśli wyzwalacz dokona tej samej zmiany w każdym wierszu, co może być wydajniejsze obsługiwane przez pojedynczą aktualizację). Nie sądzę, żeby miał na myśli, że możesz to zrobić w każdej sytuacji.
— Rauni Lillemets,

1
Rozwiązanie @ zyzof jest lepsze do wyłączania wszystkich wyzwalaczy.
— uthomas

51

Aby wyłączyć wyzwalacz

ALTER TABLE table_name DISABLE TRIGGER trigger_name

Włącz wyzwalacz

ALTER TABLE table_name ENABLE TRIGGER trigger_name

2
Możesz także użyć do tego „all”:ALTER TABLE table_name DISABLE TRIGGER all
— DenisNovac

8
SET session_replication_role = replica; 

Nie działa z PostgreSQL 9.4 na moim komputerze z Linuksem, jeśli zmienię tabelę za pomocą edytora tabel w pgAdmin i działa, jeśli zmienię tabelę za pomocą zwykłego zapytania. Ręczne zmiany w tabeli pg_trigger również nie działają bez restartu serwera, ale działa dynamiczne zapytanie, takie jak na postgresql.nabble.com ENABLE / DISABLE ALL TRIGGERS IN DATABASE . Może to być przydatne, gdy potrzebujesz trochę strojenia.

Na przykład, jeśli masz tabele w określonej przestrzeni nazw, może to być:

create or replace function disable_triggers(a boolean, nsp character varying) returns void as
$$
declare 
act character varying;
r record;
begin
    if(a is true) then
        act = 'disable';
    else
        act = 'enable';
    end if;

    for r in select c.relname from pg_namespace n
        join pg_class c on c.relnamespace = n.oid and c.relhastriggers = true
        where n.nspname = nsp
    loop
        execute format('alter table %I %s trigger all', r.relname, act); 
    end loop;
end;
$$
language plpgsql;

Jeśli chcesz wyłączyć wszystkie wyzwalacze z określoną funkcją wyzwalacza, może to być:

create or replace function disable_trigger_func(a boolean, f character varying) returns void as
$$
declare 
act character varying;
r record;
begin
    if(a is true) then
        act = 'disable';
    else
        act = 'enable';
    end if;

    for r in select c.relname from pg_proc p 
        join pg_trigger t on t.tgfoid = p.oid
        join pg_class c on c.oid = t.tgrelid
        where p.proname = f
    loop
        execute format('alter table %I %s trigger all', r.relname, act); 
    end loop;
end;
$$
language plpgsql;

Dokumentacja PostgreSQL dla katalogów systemowych


Istnieją inne opcje sterowania procesem wyzwalania spustu:

ALTER TABLE ... ENABLE REPLICA TRIGGER ... - wyzwalacz będzie strzelał tylko w trybie repliki.

ALTER TABELA ... WŁĄCZ ZAWSZE TRIGGER ... - spust będzie zawsze (oczywiście) odpalany


7

Możesz także wyłączyć wyzwalacze w pgAdmin (III):

  1. Znajdź swój stolik
  2. Rozwiń +
  3. Znajdź wyzwalacz w wyzwalaczach
  4. Kliknij prawym przyciskiem myszy i usuń zaznaczenie opcji „Wyzwalanie włączone?”

4
SET session_replication_role = replica;  

również nie pracowałem dla mnie w Postgres 9.1. używam dwóch funkcji opisanych przez Bartolo-otrita z pewnymi modyfikacjami. Zmodyfikowałem pierwszą funkcję, aby działała dla mnie, ponieważ przestrzeń nazw lub schemat muszą być obecne, aby poprawnie zidentyfikować tabelę. Nowy kod to:

CREATE OR REPLACE FUNCTION disable_triggers(a boolean, nsp character varying)
  RETURNS void AS
$BODY$
declare 
act character varying;
r record;
begin
    if(a is true) then
        act = 'disable';
    else
        act = 'enable';
    end if;

    for r in select c.relname from pg_namespace n
        join pg_class c on c.relnamespace = n.oid and c.relhastriggers = true
        where n.nspname = nsp
    loop
        execute format('alter table %I.%I %s trigger all', nsp,r.relname, act); 
    end loop;
end;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION disable_triggers(boolean, character varying)
  OWNER TO postgres;

następnie po prostu wykonuję zapytanie wybierające dla każdego schematu:

SELECT disable_triggers(true,'public');
SELECT disable_triggers(true,'Adempiere');
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.