受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

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

只要与事件触发器关联的事件在其定义所在数据库中发生,事件触发器就会被触发。 目前支持的事件有 loginddl_command_startddl_command_endtable_rewritesql_drop。 未来版本可能会增加对更多事件的支持。

38.1.1. login #

当已认证用户登录系统时,会发生 login 事件。 该事件的触发器过程中的任何缺陷都可能导致系统无法成功登录。 可以通过在连接字符串或配置文件中将 event_triggers 设为 false 来绕过这类问题。或者,也可以将系统重启到单用户模式 (该模式下事件触发器被禁用)。关于如何使用单用户模式的细节,参见 postgres 参考页。 login 事件也会在后备服务器上触发。 为防止服务器变得无法访问,这类触发器在后备服务器上运行时必须避免向数据库写 入任何内容。此外,还建议避免在 login 事件触发器中执行长 时间运行的查询。请注意,例如在 psql 中取消一个连 接,并不会取消正在执行中的 login 触发器。

关于如何使用 login 事件触发器的示例,参见 Section 38.5

38.1.2. ddl_command_start #

ddl_command_start 事件发生在 DDL 命令即将执行之前。 此处的 DDL 命令包括:

  • CREATE

  • ALTER

  • DROP

  • COMMENT

  • GRANT

  • IMPORT FOREIGN SCHEMA

  • REINDEX

  • REFRESH MATERIALIZED VIEW

  • REVOKE

  • SECURITY LABEL

ddl_command_start 也会在 SELECT INTO 命令即将执行之前发生,因为它等价于 CREATE TABLE AS

但有一个例外:对于以共享对象为目标的 DDL 命令,不会发生该事件:

  • 数据库

  • 角色(角色定义和角色成员关系)

  • 表空间

  • 参数权限

  • ALTER SYSTEM

针对事件触发器本身的命令也不会引发该事件。

在事件触发器触发之前,不会检查受影响对象究竟存在还是不存在。

38.1.3. ddl_command_end #

ddl_command_end 事件发生在与 ddl_command_start 相同的一组命令执行之后。 要获取这些 DDL 操作的更多细节,可在 ddl_command_end 事件触发器代码中使用集合返回函数 pg_event_trigger_ddl_commands()(见 Section 9.30)。注意,触发器是在这些动作已发生 之后(但在事务提交之前)触发的,因此读取系统目录时,看到的已是变更后的状态。

38.1.4. sql_drop #

对于任何删除数据库对象的操作,sql_drop 事件都发生在 ddl_command_end 事件触发器之前。请注意,除了显而易见的 DROP 命令外,某些 ALTER 命令也会触发 sql_drop 事件。

要列出已删除的对象,可在 sql_drop 事件触发器代码中使用 集合返回函数 pg_event_trigger_dropped_objects()(见 Section 9.30)。注意,触发器是在这些对象已经从 系统目录中删除之后执行的,因此已无法再查找它们。

38.1.5. table_rewrite #

table_rewrite 事件发生在表即将因 ALTER TABLEALTER TYPE 命令中的某些 操作而被重写之前。虽然还有其他控制语句也可以重写表,例如 CLUSTERVACUUM,但它们不会触发 table_rewrite 事件。要找出被重写表的 OID,请使用函数 pg_event_trigger_table_rewrite_oid();要找出重写的一个或多个 原因, 可使用函数 pg_event_trigger_table_rewrite_reason()(见 Section 9.30)。

38.1.6. 已中止事务中的事件触发器 #

事件触发器(与其他函数一样)不能在已中止的事务中执行。因此,如果 DDL 命令因 错误而失败,任何关联的 ddl_command_end 触发器都不会执行。 反之,如果 ddl_command_start 触发器因错误而失败,后续事 件触发器都不会触发,也不会尝试执行该命令本身。类似地,如果 ddl_command_end 触发器因错误而失败,DDL 语句的效果将被回 滚,就像包含该语句的事务在任何其他情况下中止时那样。

38.1.7. 创建事件触发器 #

事件触发器通过命令 CREATE EVENT TRIGGER 创建。 为了创建事件触发器,必须先创建一个返回类型为 event_trigger 的特殊函数。 该函数不需要(也不能)返回值;这个返回类型仅用于表明该函数要作为事件触发器 被调用。

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

触发器定义也可以指定一个 WHEN 条件,这样,例如, ddl_command_start 触发器就可以只针对用户希望拦截的特定命 令触发。这类触发器的一个常见用途是限制用户可执行的 DDL 操作范围。

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。