9.3 9.4 9.5 9.6 10 11 12 13 14 15 Current(16) 17
问题报告 纠错本页面

38.1. 事件触发器行为总览 #

事件触发器在其关联的事件发生于定义它的数据库中时触发。当前,唯一支持的事件有 loginddl_command_startddl_command_endtable_rewritesql_drop。 未来版本可能会增加对更多事件的支持。

当经过身份验证的用户登录系统时,会发生login事件。该事件的触发过程中的任何 错误都可能导致无法成功登录系统。可以通过在连接字符串或配置文件中将 event_triggers设置为false来规避此类错误。 或者,您也可以在单用户模式下重启系统(因为事件触发器在此模式下被禁用)。 有关使用单用户模式的详细信息,请参阅postgres参考页面。 login事件也会在备用服务器上触发。为了防止服务器变得不可访问, 这些触发器在备用服务器上运行时必须避免向数据库写入任何内容。 此外,建议避免在login事件触发器中执行长时间运行的查询。 注意,例如,在psql中取消连接不会取消正在进行的 login触发器。

ddl_command_start事件就在CREATEALTERDROPSECURITY LABELCOMMENTGRANT或者REVOKE 命令的执行之前发生。在事件触发器引发前不会做受影响对象是否存在的检查。 不过,一个例外是,这个事件不会为目标是共享对象 — 数据库、角色 以及表空间 — 的 DDL 命令发生,也不会为目标是事件触发器的 DDL 命令发生。事件触发器机制不支持这些对象类型。 ddl_command_start也会在SELECT INTO 命令的执行之前发生,因为这等价于 CREATE TABLE AS

ddl_command_end事件就在同一组命令的执行之后发生。为了 得到发生的DDL操作的更多细节,可以从 ddl_command_end事件触发器代码中使用集合返回函数 pg_event_trigger_ddl_commands()(见 Section 9.30)。注意该触发器是在那些动作 已经发生之后(但是在事务提交前)引发,并且因此系统目录会被读作已更改。

sql_drop事件为任何删除数据库对象的操作在 ddl_command_end事件触发器之前发生。要列出已经被删除的 对象,可以从sql_drop事件触发器代码中使用集合返回函数 pg_event_trigger_dropped_objects()Section 9.30)。注意该触发器是在对象已经 从系统目录删除以后执行,因此不能再查看它们。

table_rewrite事件发生在某些命令 ALTER TABLEALTER TYPE的操作 重写表之前。虽然其他控制语句也可以用来重写表, 如CLUSTERVACUUM, 但table_rewrite事件不会被它们触发。 要查找被重写表的OID,请使用函数 pg_event_trigger_table_rewrite_oid()(参见 Section 9.30)。要了解重写的原因, 请使用函数pg_event_trigger_table_rewrite_reason()

不能在一个中止的事务中执行事件触发器(其他函数也一样)。因此,如果一个 DDL 命令出现错误失败,将不会执行任何相关的 ddl_command_end触发器。反过来,如果一个 ddl_command_start触发器出现错误失败,将不会引发进一步的 事件触发器,并且不会尝试执行该命令本身。类似地,如果一个 ddl_command_end触发器出现错误失败,DDL 命令的效果将被 回滚,就像其他包含事务中止的情况中那样。

Section 38.2中有事件触发器机制所支持的完整 命令列表。

事件触发器通过命令CREATE EVENT TRIGGER创建。为了 创建一个事件触发器,你必须首先创建一个有特殊返回类型 event_trigger的函数。这个函数不一定需要返回一个值, 该返回类型仅仅是作为一种信号表示该函数要被作为一个事件触发器调用。

如果对于一个特定的事件定义了多于一个事件触发器,它们将按照触发器名称 的字母表顺序被引发。

一个触发器定义也可以指定一个WHEN条件,这样事件触 发器(例如ddl_command_start触发器)就可以只对用户 希望介入的特定命令触发。这类触发器的通常用法是用于限制用户可能执行的 DDL 操作的范围。