PostgreSQL的Event triggers
2021-01-18 14:08 abce 阅读(1372) 评论(0) 编辑 收藏 举报PostgreSQL中,常规触发器依附于单个表并捕获dml事件。而Event triggers是数据库全局性的,可以捕获ddl事件。与常规触发器一样,Event triggers可以用任何包含事件触发器支持的过程语言编写,也可以用C编写,但不能用纯SQL编写。
当与事件关联的事件在定义它的数据库中发生时,就会触发Event triggers。在11版本中,仅支持的事件是ddl_command_start,ddl_command_end,table_rewrite和sql_drop。在将来的版本中可能会添加对其他事件的支持。
ddl_command_start事件在执行CREATE,ALTER,DROP,SECURITY LABEL,COMMENT,GRANT或REVOKE命令之前发生。在触发事件触发器之前,不检查受影响的对象是否存在。但是,作为例外,针对共享对象(数据库,角色和表空间)的DDL命令或针对Event triggers本身的命令不会发生此事件。事件触发机制不支持这些对象类型。ddl_command_start也将在执行SELECT INTO命令之前发生,因为它等效于CREATE TABLE AS。
ddl_command_end事件在执行以上命令后立即发生。要获得有关已发生的DDL操作的更多详细信息,请使用ddl_command_end事件触发代码中的设置返回函数pg_event_trigger_ddl_commands()。请注意,触发器在执行操作之后(但在事务提交之前)触发,因此可以将系统目录读取为已更改。
对于任何删除数据库对象的操作,sql_drop事件就在ddl_command_end事件触发器之前发生。要列出已删除的对象,请使用sql_drop事件触发代码中的返回设置函数pg_event_trigger_dropped_objects()。请注意,触发器是在从系统目录中删除对象后执行的,因此无法再查找它们。
table_rewrite事件仅在通过命令ALTER TABLE和ALTER TYPE的某些操作重写表之前发生。尽管其他控制语句(例如CLUSTER和VACUUM)可用于重写表,但table_rewrite事件不会由它们触发。
事件触发器(与其他函数一样)无法在异常终止的事务中执行。因此,如果DDL命令由于错误而失败,则将不执行任何关联的ddl_command_end触发器。相反,如果ddl_command_start触发器因错误而失败,则不会触发其他事件触发器,也不会尝试执行命令本身。同样,如果ddl_command_end触发器因错误而失败,则DDL语句的效果将回滚,就像在其他任何情况下包含事务中止的情况一样。
使用命令CREATE EVENT TRIGGER创建事件触发器。为了创建事件触发器,必须首先创建具有特殊返回类型event_trigger的函数。此函数不需要(也可以不)返回值;返回类型仅用作将函数作为事件触发器调用的信号。
如果为一个特定事件定义了多个事件触发器,则它们将按触发器名称的字母顺序触发。
触发器定义还可以指定WHEN条件,例如,仅可以为用户希望拦截的特定命令触发ddl_command_start触发器。这种触发器的常见用法是限制用户可以执行的DDL操作的范围。
事件触发触发矩阵
Command Tag | ddl_command_start | ddl_command_end | sql_drop | table_rewrite | Notes |
---|---|---|---|---|---|
ALTER AGGREGATE |
X |
X |
- |
- |
|
ALTER COLLATION |
X |
X |
- |
- |
|
ALTER CONVERSION |
X |
X |
- |
- |
|
ALTER DOMAIN |
X |
X |
- |
- |
|
ALTER DEFAULT PRIVILEGES |
X |
X |
- |
- |
|
ALTER EXTENSION |
X |
X |
- |
- |
|
ALTER FOREIGN DATA WRAPPER |
X |
X |
- |
- |
|
ALTER FOREIGN TABLE |
X |
X |
X |
- |
|
ALTER FUNCTION |
X |
X |
- |
- |
|
ALTER LANGUAGE |
X |
X |
- |
- |
|
ALTER LARGE OBJECT |
X |
X |
- |
- |
|
ALTER MATERIALIZED VIEW |
X |
X |
- |
- |
|
ALTER OPERATOR |
X |
X |
- |
- |
|
ALTER OPERATOR CLASS |
X |
X |
- |
- |
|
ALTER OPERATOR FAMILY |
X |
X |
- |
- |
|
ALTER POLICY |
X |
X |
- |
- |
|
ALTER PROCEDURE |
X |
X |
- |
- |
|
ALTER PUBLICATION |
X |
X |
- |
- |
|
ALTER SCHEMA |
X |
X |
- |
- |
|
ALTER SEQUENCE |
X |
X |
- |
- |
|
ALTER SERVER |
X |
X |
- |
- |
|
ALTER STATISTICS |
X |
X |
- |
- |
|
ALTER SUBSCRIPTION |
X |
X |
- |
- |
|
ALTER TABLE |
X |
X |
X |
X |
|
ALTER TEXT SEARCH CONFIGURATION |
X |
X |
- |
- |
|
ALTER TEXT SEARCH DICTIONARY |
X |
X |
- |
- |
|
ALTER TEXT SEARCH PARSER |
X |
X |
- |
- |
|
ALTER TEXT SEARCH TEMPLATE |
X |
X |
- |
- |
|
ALTER TRIGGER |
X |
X |
- |
- |
|
ALTER TYPE |
X |
X |
- |
X |
|
ALTER USER MAPPING |
X |
X |
- |
- |
|
ALTER VIEW |
X |
X |
- |
- |
|
COMMENT |
X |
X |
- |
- |
Only for local objects |
CREATE ACCESS METHOD |
X |
X |
- |
- |
|
CREATE AGGREGATE |
X |
X |
- |
- |
|
CREATE CAST |
X |
X |
- |
- |
|
CREATE COLLATION |
X |
X |
- |
- |
|
CREATE CONVERSION |
X |
X |
- |
- |
|
CREATE DOMAIN |
X |
X |
- |
- |
|
CREATE EXTENSION |
X |
X |
- |
- |
|
CREATE FOREIGN DATA WRAPPER |
X |
X |
- |
- |
|
CREATE FOREIGN TABLE |
X |
X |
- |
- |
|
CREATE FUNCTION |
X |
X |
- |
- |
|
CREATE INDEX |
X |
X |
- |
- |
|
CREATE LANGUAGE |
X |
X |
- |
- |
|
CREATE MATERIALIZED VIEW |
X |
X |
- |
- |
|
CREATE OPERATOR |
X |
X |
- |
- |
|
CREATE OPERATOR CLASS |
X |
X |
- |
- |
|
CREATE OPERATOR FAMILY |
X |
X |
- |
- |
|
CREATE POLICY |
X |
X |
- |
- |
|
CREATE PROCEDURE |
X |
X |
- |
- |
|
CREATE PUBLICATION |
X |
X |
- |
- |
|
CREATE RULE |
X |
X |
- |
- |
|
CREATE SCHEMA |
X |
X |
- |
- |
|
CREATE SEQUENCE |
X |
X |
- |
- |
|
CREATE SERVER |
X |
X |
- |
- |
|
CREATE STATISTICS |
X |
X |
- |
- |
|
CREATE SUBSCRIPTION |
X |
X |
- |
- |
|
CREATE TABLE |
X |
X |
- |
- |
|
CREATE TABLE AS |
X |
X |
- |
- |
|
CREATE TEXT SEARCH CONFIGURATION |
X |
X |
- |
- |
|
CREATE TEXT SEARCH DICTIONARY |
X |
X |
- |
- |
|
CREATE TEXT SEARCH PARSER |
X |
X |
- |
- |
|
CREATE TEXT SEARCH TEMPLATE |
X |
X |
- |
- |
|
CREATE TRIGGER |
X |
X |
- |
- |
|
CREATE TYPE |
X |
X |
- |
- |
|
CREATE USER MAPPING |
X |
X |
- |
- |
|
CREATE VIEW |
X |
X |
- |
- |
|
DROP ACCESS METHOD |
X |
X |
X |
- |
|
DROP AGGREGATE |
X |
X |
X |
- |
|
DROP CAST |
X |
X |
X |
- |
|
DROP COLLATION |
X |
X |
X |
- |
|
DROP CONVERSION |
X |
X |
X |
- |
|
DROP DOMAIN |
X |
X |
X |
- |
|
DROP EXTENSION |
X |
X |
X |
- |
|
DROP FOREIGN DATA WRAPPER |
X |
X |
X |
- |
|
DROP FOREIGN TABLE |
X |
X |
X |
- |
|
DROP FUNCTION |
X |
X |
X |
- |
|
DROP INDEX |
X |
X |
X |
- |
|
DROP LANGUAGE |
X |
X |
X |
- |
|
DROP MATERIALIZED VIEW |
X |
X |
X |
- |
|
DROP OPERATOR |
X |
X |
X |
- |
|
DROP OPERATOR CLASS |
X |
X |
X |
- |
|
DROP OPERATOR FAMILY |
X |
X |
X |
- |
|
DROP OWNED |
X |
X |
X |
- |
|
DROP POLICY |
X |
X |
X |
- |
|
DROP PROCEDURE |
X |
X |
X |
- |
|
DROP PUBLICATION |
X |
X |
X |
- |
|
DROP RULE |
X |
X |
X |
- |
|
DROP SCHEMA |
X |
X |
X |
- |
|
DROP SEQUENCE |
X |
X |
X |
- |
|
DROP SERVER |
X |
X |
X |
- |
|
DROP STATISTICS |
X |
X |
X |
- |
|
DROP SUBSCRIPTION |
X |
X |
X |
- |
|
DROP TABLE |
X |
X |
X |
- |
|
DROP TEXT SEARCH CONFIGURATION |
X |
X |
X |
- |
|
DROP TEXT SEARCH DICTIONARY |
X |
X |
X |
- |
|
DROP TEXT SEARCH PARSER |
X |
X |
X |
- |
|
DROP TEXT SEARCH TEMPLATE |
X |
X |
X |
- |
|
DROP TRIGGER |
X |
X |
X |
- |
|
DROP TYPE |
X |
X |
X |
- |
|
DROP USER MAPPING |
X |
X |
X |
- |
|
DROP VIEW |
X |
X |
X |
- |
|
GRANT |
X |
X |
- |
- |
Only for local objects |
IMPORT FOREIGN SCHEMA |
X |
X |
- |
- |
|
REFRESH MATERIALIZED VIEW |
X |
X |
- |
- |
|
REVOKE |
X |
X |
- |
- |
Only for local objects |
SECURITY LABEL |
X |
X |
- |
- |
Only for local objects |
SELECT INTO |
X |
X |
- |
- |
1.创建一张用于存放ddl记录的表:
1 | CREATE TABLE ddl_history ( ID serial PRIMARY KEY , ddl_date timestamptz, ddl_tag TEXT, object_name TEXT ); |
2.定义两个函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | CREATE OR REPLACE FUNCTION log_ddl ( ) RETURNS event_trigger AS $$ DECLARE audit_query TEXT; r RECORD; BEGIN IF tg_tag <> 'DROP TABLE' THEN r := pg_event_trigger_ddl_commands ( ); INSERT INTO ddl_history ( ddl_date, ddl_tag, object_name ) VALUES ( statement_timestamp( ), tg_tag, r.object_identity ); END IF; END ; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION log_ddl_drop ( ) RETURNS event_trigger AS $$ DECLARE audit_query TEXT; r RECORD; BEGIN IF tg_tag = 'DROP TABLE' THEN FOR r IN SELECT * FROM pg_event_trigger_ddl_commands ( ) LOOP INSERT INTO ddl_history ( ddl_date, ddl_tag, object_name ) VALUES ( statement_timestamp( ), tg_tag, r.object_identity ); END LOOP; END IF; END ; $$ LANGUAGE plpgsql; |
3.创建两个事件触发器
1 2 3 | CREATE EVENT TRIGGER log_ddl_info ON ddl_command_end EXECUTE PROCEDURE log_ddl(); CREATE EVENT TRIGGER log_ddl_drop_info ON sql_drop EXECUTE PROCEDURE log_ddl_drop(); |
4.执行ddl测试
1 2 3 4 5 6 | CREATE TABLE testtable (id int , first_name text); ALTER TABLE testtable ADD COLUMN last_name text; ALTER TABLE testtable ADD COLUMN midlname text; ALTER TABLE testtable RENAME COLUMN midlname TO middle_name; ALTER TABLE testtable DROP COLUMN middle_name; DROP TABLE testtable;<br> SELECT * FROM ddl_history; |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
2017-01-18 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误