2016-07-12 3 views
0

私のテーブルには、更新を防ぐトリガーがあります。そのため、行は効果的に不変のポスト挿入になります。pg_class.relhastriggersは `ALTER TABLE ... DISABLE TRIGGER USER`の代わりに安全ですか?

(例えば新しい計算フィールドを追加)このテーブルを遡及更新を実行するために必要とする場合、私は、次のアプローチをとっている。

ALTER TABLE my_table DISABLE TRIGGER USER; 

UPDATE my_table 
    SET x = (...); 

ALTER TABLE my_table ENABLE TRIGGER USER; 

このアプローチの欠点は、それがAccessExclusiveLockを必要とすることです。

私が使用するために、次は UPDATEの行は、他のクエリによって更新されないことが保証されている与えられた、安全であれば、私は思っていた

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; 

私がこれまで試してみましたが、このことを示唆していますこのトランザクションの外では、トリガーは正常に引き続き適用されます。

また、私の使用事例で実際に安全である場合、安全ではない状況は何ですか?

私はPostgres 9.4.8を使用しています。

おかげで、よりDISABLE TRIGGER ALLのように動作しますrelhastriggersを更新

答えて

1

:-)、すなわち、それはまた、外部キーおよび繰延一意性チェックのために使用される内部トリガを無効にします。これはあなたの場合には問題になるかもしれません。

pg_classの直接的な更新がPostgresコードベースのいくつかの仮定に違反しているかどうかわかりません。しかし、一般に、カタログ表をハッキングすることは本質的に安全ではありません。 今すぐが壊れていなくても、将来のバージョンではこれが保証されることはありません。

REVOKE UPDATE ON my_tableは、更新をブロックするためのはるかに良いアプローチです。スーパーユーザは自動的に免除されるので、UPDATE pg_classの許可を得た人は誰でもmy_tableに問題はありません。

何らかの理由で本当にトリガーでこれを行う必要がある場合は、それを回避する別の方法があります(多少ハックリですが、少なくともサポートされています)。既定では、レプリケーションプロセスによってトリガーは発生しません(句ALTER TABLEで制御できます)。これは、あなたがレプリケータ偽装によってトリガーをバイパスできることを意味します:カタログ更新と同様に

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

を、これはまた、任意の内部制約トリガを無効にします。

関連する問題