赞
踩
专栏内容:
在postgresql 除了普通触发器外,还支持事件触发器(event trigger)。
普通触发器在单个表上捕获 DML事件,与普通触发器不同,事件触发器是数据库的全局触发器,能够捕获 DDL事件,它不限定于那张表。
与常规触发器一样,事件触发器可以使用任何支持事件触发器功能的过程语言或 C 语言来编写。
事件触发器支持四种事件类型:
下面看看这四种事件类型详细的机制。
ddl_command_start
事件,可以在CREATE
, ALTER
, DROP
, SECURITY LABEL
, COMMENT
, GRANT
和 REVOKE
这些命令时触发。
它触发的时机是在命令执行之前,也就是不会检查受影响的对象是否存在。
对于针对数据库级的共享对象(如数据库、角色和表空间)或针对事件触发器本身的 DDL 命令,此事件不会触发。
对于 SELECT INTO 命令,它也会触发,因为这与 CREATE TABLE AS 命令等效。
ddl_command_end
与ddl_command_start
触发的DDL命令相同;当然触发器中发生了错误时,事务就会中止,产生回滚。
ALTER TABLE
或 ALTER TYPE
命令操作导致表的被重写时,会触发 table_rewrite
事件;CLUSTER
和 VACUUM
)也可以引发表的重写,但它们不会触发 table_rewrite 事件;注意,不是所有的alter table
会引起表的重写。
这里有一个表的重写的概念,简单理解就是把一张表的所有数据又写入了一遍,保持数据的内容与表的字段定义一致。
比如通过alter table
新增一列:
当表中的数据非常多时,表的重写是非常可怕的,有两种方式避免产生:
事件触发器的创建步骤与普通触发器类似,也需要先创建触发器执行函数,然后再创建触发器。
事件触发器的执行函数,也是没有参数,但是返回值必须是event_trigger类型;
CREATE OR REPLACE FUNCTION trigger_function()
RETURNS event_trigger
LANGUAGE plpgsql AS
$$
BEGIN
...
END
$$;
CREATE EVENT TRIGGER trigger_name
ON [ddl_command_start
| ddl_command_end
| sql_drop
| table_rewrite ]
EXECUTE FUNCTION trigger_function();
create event
命令创建事件触发器;on
子句后面,指定触发的事件;这些事件作用的对角为当前数据库范围;excute function
指定执行函数;表的重写,在平时维护数据库是都不会太关注,最新的postgresql 也优化了很多,非必要场景已经不再出现,但是它还是非常的危险,尤其在生产环境上进行维护时。
下面我们通过 table_rewrite事件触发器,来制定一个限制策略,来避免对业务的影响。
通过事件触发器函数来制定rewrite事件触发的规则:
employee
不能有表的重写,它是基础表,数据量和业务都比较多,所以限制它;对于上述三条规则,实现如下函数;
CREATE OR REPLACE FUNCTION rewrite_rule_fun()
RETURNS event_trigger
LANGUAGE plpgsql AS
$$
DECLARE
table_oid oid := pg_event_trigger_table_rewrite_oid();
current_hour integer := extract('hour' from current_time);
pages integer;
max_pages integer := 100;
BEGIN
-- 规则一
IF pg_event_trigger_table_rewrite_oid() = 'public.employee'::regclass
THEN
RAISE EXCEPTION 'you''re not allowed to rewrite the table %',
table_oid::regclass;
END IF;
-- 规则二
SELECT INTO pages relpages FROM pg_class WHERE oid = table_oid;
IF pages > max_pages
THEN
RAISE EXCEPTION 'rewrites only allowed for table with less than % pages',
max_pages;
END IF;
-- 规则三
IF current_hour NOT BETWEEN 1 AND 6
THEN
RAISE EXCEPTION 'rewrites only allowed between 1am and 6am';
END IF;
END;
$$;
说明
pg_event_trigger_table_rewrite_oid
获得引起表重写的数据库对象OID;pg_class
表中,但是它不是非常准确的值,依赖于analyze
;制定好策略之后,就启用吧,下面创建当前数据库的事件触发器。
CREATE EVENT TRIGGER tri_rewrite_rule
ON table_rewrite
EXECUTE FUNCTION rewrite_rule_fun();
postgresql 中的事件触发器,可以指定的事件有 ddl_command_start
ddl_command_end
table_rewrite
sql_drop
,
它可以让我们制定对这些事件的约束策略,当然也可以实现之前的审计案例。
其中特别要注意表的重写事件,它是一个经常被忽视,对业务影响非常大的事件,可以通过一系列规则进行限制。
非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!
作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。
注:未经同意,不得转载!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。