支持的版本: 当前 (17) / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3

38.1. 事件触发器行为概述 #

当与其关联的事件发生在定义它的数据库中时,事件触发器就会被触发。目前,唯一支持的事件是 loginddl_command_startddl_command_endtable_rewritesql_drop。未来版本可能会增加对其他事件的支持。

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

ddl_command_start 事件发生在执行 CREATEALTERDROPSECURITY LABELCOMMENTGRANTREVOKE 命令之前。在触发事件触发器之前,不会检查受影响的对象是否存在。但是,作为例外,此事件不会发生在针对共享对象(数据库、角色和表空间)的 DDL 命令,或针对事件触发器本身的命令。事件触发器机制不支持这些对象类型。ddl_command_start 也会在执行 SELECT INTO 命令之前发生,因为这等同于 CREATE TABLE AS

ddl_command_end 事件发生在执行同一组命令之后。要获取有关DDL操作的更多详细信息,请使用来自 ddl_command_end 事件触发器代码的集合返回函数 pg_event_trigger_ddl_commands() (请参阅第 9.30 节)。请注意,触发器在操作发生后(但在事务提交之前)触发,因此可以读取系统目录中已经更改的内容。

sql_drop 事件发生在任何删除数据库对象的操作的 ddl_command_end 事件触发器之前。要列出已删除的对象,请使用来自 sql_drop 事件触发器代码的集合返回函数 pg_event_trigger_dropped_objects() (请参阅 第 9.30 节)。请注意,触发器是在从系统目录中删除对象后执行的,因此无法再查找它们。

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

事件触发器(与其他函数一样)无法在中止的事务中执行。因此,如果 DDL 命令失败并出现错误,则不会执行任何关联的 ddl_command_end 触发器。相反,如果 ddl_command_start 触发器失败并出现错误,则不会触发其他事件触发器,也不会尝试执行命令本身。同样,如果 ddl_command_end 触发器失败并出现错误,则 DDL 语句的效果将回滚,就像在包含事务中止的任何其他情况下一样。

有关事件触发器机制支持的命令的完整列表,请参阅第 38.2 节

使用命令 CREATE EVENT TRIGGER 创建事件触发器。为了创建事件触发器,您必须首先创建一个具有特殊返回类型 event_trigger 的函数。此函数不需要(也不能)返回值;返回类型仅作为函数要作为事件触发器调用的信号。

如果为特定事件定义了多个事件触发器,它们将按触发器名称的字母顺序触发。

触发器定义还可以指定 WHEN 条件,以便例如,只有当用户希望拦截特定命令时,才能触发 ddl_command_start 触发器。此类触发器的一个常见用途是限制用户可以执行的 DDL 操作范围。

提交更正

如果您在文档中发现任何不正确、与特定功能的使用体验不符或需要进一步澄清的地方,请使用此表单报告文档问题。