Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

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

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

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

在执行CREATEALTERDROPSECURITY LABELCOMMENTGRANTREVOKE命令之前,会发生ddl_command_start事件。在事件触发器触发之前,不会检查受影响对象是否存在。不过,例外情况是,此事件不会针对下面这些对共享对象(数据库、角色和表空间)执行的 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 节)。请注意,该触发器在从系统目录中删除对象后执行,因此无法再查找它们。

对于 ALTER TABLEALTER TYPE 命令所执行某些操作,table_rewrite 事件会在某个表被改写之前触发。虽然可使用 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 操作范围进行限制。