2016-07-12 6 views
0

Auf meinem Tisch habe ich einen Auslöser, der Updates verhindert, was bedeutet, dass Zeilen nach dem Einfügen effektiv unveränderbar sind.Ist pg_class.relhastriggers eine sichere Alternative zu `ALTER TABLE ... DISABLE TRIGGER USER`?

Wenn retrospektive Aktualisierungen zu dieser Tabelle auszuführen benötigen (zum Beispiel ein neues berechnetes Feld hinzufügen) ich folgende Vorgehensweise getroffen haben:

ALTER TABLE my_table DISABLE TRIGGER USER; 

UPDATE my_table 
    SET x = (...); 

ALTER TABLE my_table ENABLE TRIGGER USER; 

Der Nachteil dieses Ansatzes ist, dass es eine AccessExclusiveLock erfordert.

Ich frage mich, ob die folgende sicher ist für mich gegeben zu verwenden, ist sichergestellt, dass die Zeilen in der UPDATE werden von anderen Abfragen aktualisiert werden nicht:

BEGIN; 
    UPDATE pg_class 
    SET relhastriggers = FALSE 
    WHERE relname = 'my_table'; 

    UPDATE my_table 
    SET x = (...); 

    UPDATE pg_class 
    SET relhastriggers = TRUE 
    WHERE relname = 'my_table'; 
COMMIT; 

Was ich bisher versucht, legt dies nahe, ist sicher und außerhalb dieser Transaktion werden die Trigger weiterhin normal angewendet.

Auch, wenn es in der Tat sicher für meinen Anwendungsfall ist, unter welchen Umständen wäre es nicht sicher?

Ich benutze Postgres 9.4.8.

Danke :-)

Antwort

1

relhastriggers aktualisiert mehr verhält sich wie DISABLE TRIGGER ALL, das heißt es wird auch die interne Auslöser für Fremdschlüssel und latente Einmaligkeit Prüfungen verwendet deaktivieren. Dies kann in Ihrem Fall ein Problem sein oder nicht.

Ich weiß nicht, ob eine direkte Aktualisierung von pg_class einige Annahmen verletzt, die in irgendeiner Ecke der Postgres-Codebasis gemacht werden. Im Allgemeinen ist das Hacken von Katalogtabellen jedoch inhärent unsicher; auch wenn es nichts jetzt bricht, gibt es keine Garantie, dass dies in zukünftigen Versionen der Fall sein wird.

REVOKE UPDATE ON my_table ist ein weitaus besserer Ansatz zum Blockieren von Updates. Superuser sind automatisch ausgenommen, so dass jeder mit der Berechtigung UPDATE pg_class kein Problem mit my_table haben wird.

Wenn Sie dies aus irgendeinem Grund wirklich mit einem Auslöser tun müssen, gibt es einen anderen (etwas hacky, aber zumindest unterstützt) Weg, es zu umgehen. Standardmäßig werden Trigger nicht von Replikationsprozessen ausgelöst (obwohl dies über die ENABLE ALWAYS-Klausel von ALTER TABLE gesteuert werden kann). Dies bedeutet, dass Sie durch Identitätswechsel einen Replikator der Trigger umgehen können:

BEGIN; 
    SET LOCAL session_replication_role TO replica; 
    UPDATE my_table SET x = (...); 
COMMIT; 

Wie bei dem Katalog-Update, das wird auch deaktivieren jede interne Einschränkung auslöst.

Verwandte Themen