PostgreSQL中事件触发器Event Trigger

ops/2024/12/17 13:59:50/

在PostgreSQL中,事件触发器(Event Trigger)是一种特殊的触发器类型,它允许你在特定的数据库系统事件发生时执行特定的操作。与普通的触发器不同,事件触发器并不与特定的表或视图相关联,而是与数据库级别的全局事件相关联。

参考官方文档如下
https://www.postgresql.org/docs/16/functions-event-triggers.html

事件触发器的特点

  1. 全局作用:事件触发器作用于整个数据库实例,而不是单个表或视图。
  2. 系统事件:它们响应的是数据库系统级的事件,如DDL(数据定义语言)命令的执行、配置参数的更改、日志文件的切换等。
  3. 灵活性:可以定义复杂的响应逻辑,通过PL/pgSQL、PL/Tcl、PL/Perl等过程语言来实现。

事件触发器的使用场景

  • 审计和日志记录:记录所有DDL操作的日志,以便进行审计或回滚。
  • 安全策略实施:防止未经授权的DDL更改,或确保在更改前满足某些条件。
  • 自动化任务:在数据库达到特定条件时自动执行维护任务,如清理日志、备份等。

事件触发器的创建

创建事件触发器需要两个步骤:

  1. 定义触发器函数:这个函数将包含事件发生时需要执行的逻辑。
  2. 创建事件触发器:将这个触发器函数与一个或多个特定的事件关联起来。
示例:记录DDL操作
  1. 定义触发器函数
CREATE TABLE ddl_log(command_text varchar(64), user_name varchar(32), command_time datetime);CREATE  FUNCTION log_ddl_commands()RETURNS event_trigger LANGUAGE plpgsql AS $$
DECLAREobj record;
BEGIN-- Capturing Changes at Command End FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands ()LOOPINSERT INTO ddl_log (command_text,user_name,command_time,obj_name,obj_id)values(tg_tag,current_user,now(),obj.schema_name,obj.object_identity);END LOOP;
END
$$;

在这个例子中,我们创建了一个名为log_ddl_commands的函数,它会在DDL命令执行时插入一条记录到ddl_log表中。这个表需要事先创建,并包含相应的列来存储命令文本、用户名和命令执行时间。

Capturing Changes at Command End

  • pg_event_trigger_ddl_commands returns a list of DDL commands executed by each user action, when invoked in a function attached to a ddl_command_end event trigger. If called in any other context, an error is raised.
  • pg_event_trigger_ddl_commands returns one row for each base command executed; some commands that are a single SQL sentence may return more than one row. This function returns the following columns:
    在这里插入图片描述
  1. 创建事件触发器
CREATE EVENT TRIGGER ddl_audit_trigger ON ddl_command_end EXECUTE FUNCTION log_ddl_commands();

在这个例子中,我们创建了一个名为ddl_audit_trigger的事件触发器,它会在任何CREATE TABLEALTER TABLE命令执行结束时调用log_ddl_commands函数。

-- 创建一个表,测试事件触发器是否正确执行
superdb=#  create table t_event_trigger(id int);
CREATE TABLE
-- 查询DDL变更日志记录
superdb=# select * from  ddl_log;command_text | user_name |        command_time        | obj_name |         obj_id
--------------+-----------+----------------------------+----------+------------------------CREATE TABLE | super     | 2024-12-13 19:55:33.232567 | public   | public.t_event_trigger
(1 rows)
-- 给表增加字段,并查询DDL变更日志记录
superdb=# alter table t_event_trigger add column infoname varchar(32);
ALTER TABLE
superdb=# select * from ddl_log;command_text | user_name |        command_time        | obj_name |         obj_id
--------------+-----------+----------------------------+----------+------------------------CREATE TABLE | super     | 2024-12-13 19:55:33.232567 | public   | public.t_event_triggerALTER TABLE  | super     | 2024-12-13 19:57:45.244284 | public   | public.t_event_trigger
(3 rows)
-- 可以观察导,事件触发器是否正确执行,DDL变更日志已经成功插入导ddl_log

Processing Objects Dropped by a DDL Command

  • pg_event_trigger_dropped_objects returns a list of all objects dropped by the command in whose sql_drop event it is called. If called in any other context, an error is raised. This function returns the following columns:
    在这里插入图片描述
-- 创建函数用于记录DDL删除事件日志
CREATE FUNCTION log_ddl_commands_for_drops()RETURNS event_trigger LANGUAGE plpgsql AS $$
DECLAREobj record;
BEGINFOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()LOOPINSERT INTO ddl_log (command_text,user_name,command_time,obj_name,obj_id)values(tg_tag,current_user,now(),obj.schema_name,obj.object_identity);END LOOP;
END;
$$;
-- 创建事件触发器
CREATE EVENT TRIGGER ddl_audit_trigger_for_drops ON sql_drop EXECUTE FUNCTION log_ddl_commands_for_drops();-- 删除表,测试事件触发器是否正确执行
superdb=# drop table t_event_trigger;
DROP TABLEsuperdb=# select * from  ddl_log;command_text   | user_name |        command_time        | obj_name |               obj_id
-----------------+-----------+----------------------------+----------+-------------------------------------CREATE TABLE    | super     | 2024-12-13 19:55:33.232567 | public   | public.t_event_triggerALTER TABLE     | super     | 2024-12-13 19:57:45.244284 | public   | public.t_event_triggerCREATE FUNCTION | super     | 2024-12-13 20:11:23.028464 | public   | public.log_ddl_commands_for_drops()DROP TABLE      | super     | 2024-12-13 20:12:33.692562 | public   | public.t_event_triggerDROP TABLE      | super     | 2024-12-13 20:12:33.692562 | public   | public.t_event_triggerDROP TABLE      | super     | 2024-12-13 20:12:33.692562 | public   | public.t_event_trigger[]
(7 rows)

事件触发器的限制

  • 事件触发器不能回滚它们所执行的操作,如果触发器函数中的操作失败,它不会阻止已经发生的DDL命令。
  • 由于事件触发器作用于整个数据库实例,因此它们可能会对性能产生影响,特别是在处理大量并发DDL操作时。

总结

事件触发器是PostgreSQL中强大的工具,允许数据库管理员在数据库级别实施全局策略和执行自动化任务。通过合理使用事件触发器,可以有效地提高数据库的安全性、可维护性和可操作性。


http://www.ppmy.cn/ops/142656.html

相关文章

AI技术架构:从基础设施到应用

人工智能(AI)的发展,正以前所未有的速度重塑我们的世界。了解AI技术架构,不仅能帮助我们看懂 AI 的底层逻辑,还能掌握其对各行业变革的潜力与方向。 一、基础设施层:AI 技术的坚实地基 基础设施层是 AI 技…

metinfo的csrf漏洞复现

http://localhost/metinfo/install/index.php 管理员admin登录 抓修改信息包 进入点击受害链接 localhost/333.html 管理员被修改密码原来root错误被强制退出 输入密码123456登录正常

LeetCode-Golang之【5. 最长回文子串】

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 示例 1: 输入: “babad” 输出: “bab” 注意: “aba” 也是一个有效答案。 示例 2: 输入: “cbbd” 输出: “bb” 本算法采用 动态规划去解析 func longes…

RK3588开发笔记-Buildroot编译Qt5WebEngine-5.15.10

目录 前言 一、Qt5WebEngine简介 二、Qt5WebEngine编译 总结 前言 Rockchip RK3588是一款强大的多核处理器,广泛应用于边缘计算、人工智能、嵌入式系统等领域。为了在RK3588上运行自定义的Linux系统,并使用Qt5WebEngine进行Web内容渲染,Buildroot是一个非常合适的工具。本…

简单的Java小项目

学生选课系统 在控制台输入输出信息&#xff1a; 在eclipse上面的超级简单文件结构&#xff1a; Main.java package experiment_4;import java.util.*; import java.io.*;public class Main {public static List<Course> courseList new ArrayList<>();publi…

十七、临时容器kubectl debug

临时容器 一、从镜像角度看容器安全 传统架构,黑客进来,提权后,会直接操作应用,危险。 K8S,黑客从pod入侵,通过pod渗透到K8S集群,被入侵会被当做矿机,被植入sidecar 所以生产中尽量不用root账户,并且pod没有bash和sh。 二、临时容器 生产pod不建议开启bash和sh,…

校园失物招领小程序ssm+论文源码调试讲解

2.系统开发环境 2.1 JSP技术 JSP在web技术中的位置也很重要&#xff0c;对于刚进入编程行业的人们来说&#xff0c;编程语言JSP相对比较好学&#xff0c;而且也有很多高级特性[15]。在开发程序的工作中&#xff0c;jsp经常被使用到&#xff0c;例如&#xff0c;收集表单数据、…

商品订单接口获取及作用详解

引言 在电商平台的后台管理中&#xff0c;订单接口扮演着至关重要的角色。它不仅能够帮助商家实时掌握订单状态&#xff0c;还能提供订单的详细信息&#xff0c;从而优化用户体验和提高运营效率。本文将详细介绍如何获取商品订单接口&#xff0c;并解析其作用。 一、商品订单…