PostgreSQLのTriggerが発火しないのはsession_replication_roleの設定値がreplicaになっていたから

タイトルだけで完結する内容ですが、ハマった記念に残しておきます

やったこと

AWS Aurora PostgreSQLにFunction, Triggerを作成して、「特定のテーブルAのデータが更新されたら、テーブルBにデータを登録/更新する」ようにした

テーブルAにデータ登録、更新、削除どれを行ってもテーブルBにデータが連携されない

根本原因はDBパラメータグループの設定値session_replication_roleがreplica になっていることでした

この値をorigin に変更すると、正常にTriggerが発火した

原因調査

ENABLE REPLICA TRIGGER

たまたまPostgreSQL 9.5.4 のサイトに辿り着き、Triggerの有効/無効を設定する方法は「ALTER TABLE …. ENABLE TRIGGER …」だけではなく、「ALTER TABLE …. ENABLE REPLICA TRIGGER …」も存在することを知りました

ALTER TABLE test_schema.table_a ENABLE REPLICA TRIGGER table_a_trigger

これを実行するとtriggerが正常に発火し、意図した挙動になったことから、原因はREPLICA 周りの設定であることが推測できました

TRIGGERとREPLICA TRIGGERの違い

ChatGPTが教えてくれた

ENABLE TRIGGER: このコマンドは、トリガーをデフォルトのトリガーモード(通常のトリガーモード)で有効にします。
トリガーモード:
BEFORE: トリガーが対象の操作(INSERT, UPDATE, DELETEなど)が実行される前に発火します。
AFTER: トリガーが対象の操作が完了した後に発火します。

ENABLE REPLICA TRIGGER: このコマンドは、トリガーをレプリカ(複製)ノードでのみ発火するモードで有効にします。
レプリカ(複製)ノード:
レプリカノードは、主(マスター)ノードからのデータの複製を持つスタンバイノードやレプリカノードを指します。
Auroraのクラスターでは、レプリカノードが自動的に作成される場合があります。

適用シナリオ
ENABLE TRIGGER:
主に、トリガーが主ノードとレプリカノードの両方で発火する場合や、主にデータの整合性を保つために使用されます。
ENABLE REPLICA TRIGGER:
レプリカノードでのみトリガーを発火させたい場合や、レプリカノードでのリソース使用量を削減したい場合に使用されます。

つまり主ノードとレプリカノードのtirggerの挙動を変えるための設定が可能なんですね

session_replication_role

replica triggerについて調べていると、triggerを一時的に無効にしたい場合にsession_replication_roleの値をイジる方法がいくつかヒットしました
PostgreSQLで一時的にtriggerを全て無効する方法
Studio ODIN – blog風小ネタ集 > PostgreSQL で、一時的に全てのトリガーを無効にする

SET session_replication_role = replica;


defaultではsession_replication_roleはoriginになっているところをreplicaに変える方法
どうやら裏技的に使われている様子

なので僕がいじっているPostgresのsession_replication_roleを値を確認しました

SELECT name, setting, boot_val, reset_val, unit
 FROM pg_settings
 where name='session_replication_role';

裏技が使われてました

DBを管理してる方が一時的に全てのtriggerを無効にするために設定していたらしく、
結局はDBパラメータグループの値を元に戻すことでTriggerが正常に動く状態になり、めでたし!

まとめ

PostgreSQLのレプリケーションについて意識する良い機会でした
この本読んで勉強しよう!
[改訂新版]内部構造から学ぶPostgreSQL 設計・運用計画の鉄則 (Software Design plus)