【postgresql初级使用】事件触发器event trigger,被忽略的table rewrite,组合策略保障重大操作

事件触发器(event trigger)

专栏内容

  • postgresql使用入门基础
  • 手写数据库toadb
  • 并发编程

个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

文章目录

  • 事件触发器(event trigger)
  • 概述
  • 原理机制
    • ddl_command_start事件
    • ddl_command_end事件
    • table_rewrite事件
      • table rewrite触发
    • sql_drop事件
  • 语法
    • 创建触发器的函数
    • 创建事件触发器
  • 案例分析
    • 策略制定
    • 启用约束策略
  • 总结
  • 结尾

概述


在postgresql 除了普通触发器外,还支持事件触发器(event trigger)。

普通触发器在单个表上捕获 DML事件,与普通触发器不同,事件触发器是数据库的全局触发器,能够捕获 DDL事件,它不限定于那张表。

与常规触发器一样,事件触发器可以使用任何支持事件触发器功能的过程语言或 C 语言来编写。

原理机制


事件触发器支持四种事件类型:

  • ddl_command_start,在DDL执行前触发;
  • ddl_command_end,在DDL执行后触发;
  • table_rewrite,表的重写时触发;
  • sql_drop,删除数据库时会触发;

下面看看这四种事件类型详细的机制。

ddl_command_start事件

  • ddl_command_start事件,可以在CREATE, ALTER, DROP, SECURITY LABEL, COMMENT, GRANTREVOKE这些命令时触发。

  • 它触发的时机是在命令执行之前,也就是不会检查受影响的对象是否存在。

  • 对于针对数据库级的共享对象(如数据库、角色和表空间)或针对事件触发器本身的 DDL 命令,此事件不会触发。

  • 对于 SELECT INTO 命令,它也会触发,因为这与 CREATE TABLE AS 命令等效。

ddl_command_end事件

  • ddl_command_endddl_command_start触发的DDL命令相同;
  • 在触发器中,要获得执行的DDL的信息,可以通过调用 pg_event_trigger_ddl_commands() 函数;
  • 触发器在DDL动作发生后(但在事务提交之前)触发,因此可以读取已更改的数据字典。

当然触发器中发生了错误时,事务就会中止,产生回滚。

table_rewrite事件

  • 当执行某些 ALTER TABLEALTER TYPE 命令操作导致表的被重写时,会触发 table_rewrite 事件;
  • 其他控制语句(如 CLUSTERVACUUM)也可以引发表的重写,但它们不会触发 table_rewrite 事件;

注意,不是所有的alter table会引起表的重写。

table rewrite触发

这里有一个表的重写的概念,简单理解就是把一张表的所有数据又写入了一遍,保持数据的内容与表的字段定义一致。

比如通过alter table 新增一列:

  • 如果此列不指定默认值时,填充就是空值,此时不会引发表的重写,只是修改了表的定义;
  • 如果新增列指定了值,但值是一个相同的默认值;在postgresql 11以前的版本,会引发表的重写,将该值更新到每一行数据上;pg11的版本中做了优化,也只记录到表定义中;
  • 而对于新增列,与时间相关的,采用了不同的值,那么就会触发表的重写,会将新列的值更新到每一行数据上;

当表中的数据非常多时,表的重写是非常可怕的,有两种方式避免产生:

  • 一是通过软件开发规范约束,对于表重写的DDL,先设置空值,再用update进行更新;
  • 二是采用table_rewrite事件,制定执行的策略,限制执行用户的权限,同时限制当表大于多少时禁止执行;

sql_drop事件

  • 当执行任何删除数据库对象的操作(如 DROP TABLE、DROP INDEX 等)时,在 ddl_command_end 事件之前会触发 sql_drop 事件。
  • 要列出已删除的对象,可以使用 pg_event_trigger_dropped_objects() 函数。这个函数也是集合返回函数,可以在 sql_drop 事件触发器的代码中使用。
  • 要特别注意的是,触发器在对象已经从系统目录中删除后执行,因此无法再查找这些对象。

语法


事件触发器的创建步骤与普通触发器类似,也需要先创建触发器执行函数,然后再创建触发器。

创建触发器的函数

事件触发器的执行函数,也是没有参数,但是返回值必须是event_trigger类型;

CREATE OR REPLACE FUNCTION trigger_function()RETURNS event_triggerLANGUAGE plpgsql AS
$$
BEGIN
...
END
$$;

创建事件触发器

CREATE EVENT TRIGGER trigger_nameON [ddl_command_start | ddl_command_end | sql_drop | table_rewrite ]EXECUTE FUNCTION trigger_function();
  • 使用 create event命令创建事件触发器;
  • on子句后面,指定触发的事件;这些事件作用的对角为当前数据库范围;
  • 最后excute function 指定执行函数;

案例分析


表的重写,在平时维护数据库是都不会太关注,最新的postgresql 也优化了很多,非必要场景已经不再出现,但是它还是非常的危险,尤其在生产环境上进行维护时。

下面我们通过 table_rewrite事件触发器,来制定一个限制策略,来避免对业务的影响。

策略制定

通过事件触发器函数来制定rewrite事件触发的规则:

  • 核心业务表 employee 不能有表的重写,它是基础表,数据量和业务都比较多,所以限制它;
  • 其它表,当表的数据块大于100时,说明表中数据量比较大,也不允许;那样会引起IO峰值;
  • 另外,此类操作只允许在凌晨1-6点进行操作,此时间段业务非常少;

对于上述三条规则,实现如下函数;

CREATE OR REPLACE FUNCTION rewrite_rule_fun()RETURNS event_triggerLANGUAGE plpgsql AS
$$
DECLAREtable_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'::regclassTHENRAISE 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_pagesTHENRAISE EXCEPTION 'rewrites only allowed for table with less than % pages',max_pages;END IF;-- 规则三IF current_hour NOT BETWEEN 1 AND 6THENRAISE 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_ruleON table_rewriteEXECUTE FUNCTION rewrite_rule_fun();

总结


postgresql 中的事件触发器,可以指定的事件有 ddl_command_start ddl_command_end table_rewrite sql_drop,

它可以让我们制定对这些事件的约束策略,当然也可以实现之前的审计案例。

其中特别要注意表的重写事件,它是一个经常被忽视,对业务影响非常大的事件,可以通过一系列规则进行限制。

结尾


非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/26976.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OCP-043之:数据库备份操作

1 RMAN备份操作 1.1 基本操作 基本的控制和数据文件备份 RMAN> CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO /tmp/backup/cs_%F;new RMAN configuration parameters: CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO /tmp/backu…

java中为什么main方法是public static void main(String [] args)

问题 为什么java的main方法是 public static void main(String [] args),为什么要用public 、static、void 修饰 当然也可以这样写 public static void main(String... args) 问题解答 main 方法是Java程序的入口,在java运行时&a…

定时清理rocketmq日志--crontab

1、背景 之前在部署rocketmq的时候未修改日志路径,导致在用户目录下有日志数据写入。因不方便修改或空间足够可正常写入,但日志量过大需清理,现添加定时任务执行。 2、规划: 目前测试阶段,所以时间是可变的&#xf…

DTU为何应用如此广泛?

1.DTU是什么 DTU(数据传输单元)是一种无线终端设备,它的核心功能是将串口数据转换为IP数据或将IP数据转换为串口数据,并通过无线通信网络进行传送。DTU通常内置GPRS模块,能够实现远程数据的实时传输,广泛应用于工业自动化、远程监…

Redis高级特性和应用:慢查询、Pipeline、事务、Lua

Redis提供了许多高级特性,可以帮助优化和管理系统性能。本文将介绍Redis的慢查询、Pipeline、事务和Lua脚本的使用及其相关配置。 Redis的慢查询 慢查询日志是开发和运维人员定位系统慢操作的重要工具。Redis也提供了类似的功能,通过记录超过预设阀值的…

【Kafka专栏 08】ZooKeeper的Watch机制:不就是个“小喇叭”吗?

作者名称:夏之以寒 作者简介:专注于Java和大数据领域,致力于探索技术的边界,分享前沿的实践和洞见 文章专栏:夏之以寒-kafka专栏 专栏介绍:本专栏旨在以浅显易懂的方式介绍Kafka的基本概念、核心组件和使用…

LeetCode 619, 58, 24

目录 619. 只出现一次的最大数字题目链接表要求知识点思路代码使用where限制:使用having限制: 58. 最后一个单词的长度题目链接标签Java.split()思路代码 不使用Java的API思路代码 24. 两两交换链表中的节点题目链接标签要求思路代码 619. 只出现一次的最…

【blender特效】卡通火焰

核心思想就是通过多个不同缩放尺寸的沃罗诺伊叠加,分别构成火焰的大型,中型和小型(形状),最后通过自发光纹理实现火焰加亮。 用的是ev渲染,完全可以把噪音贴图都烘焙出来,自己改改shader就可以扔…

华为OD刷题C卷 - 每日刷题 29(机器人仓库搬砖,爱吃蟠桃的孙悟空)

1、(机器人仓库搬砖): 这段代码是解决“机器人仓库搬砖”的问题。它提供了一个Java类Main,其中包含main方法和getMinEnergy方法,用于计算机器人每小时充能的最小能量格数,以确保在8小时内搬完所有砖块。 …

C++14 新特性:std::make_unique 和 constexpr

今天介绍的 std::unique_ptr 和 constexpr的用法比较简单,所以放到一篇文章中进行介绍。 1、std::make_unique 首先来看 std::unique_ptr,在 C11 中引入了智能指针和std::unique_ptr,为资源管理提供了更安全、更简洁的手段。但是 C11 缺少了…

STM32无法烧写程序的故障排除

如果你在使用STM32微控制器时遇到无法烧写程序的问题,可以按以下步骤进行故障排除: 1. 确认硬件连接 检查电源:确保STM32板子正确供电。调试器连接:确认ST-LINK调试器或其他编程工具与STM32开发板的连接无误,尤其是S…

jQuery如何实现一个轮播图左右翻页的功能

当使用jQuery来实现一个轮播图左右翻页的功能时&#xff0c;你可以遵循以下步骤&#xff1a; HTML结构&#xff1a;首先&#xff0c;你需要创建一个HTML结构来包含轮播图的图片。 <div class"carousel"> <div class"carousel-images"> <…

利用python爬虫采集苹果公司各产品销售收入统计报告

数据为2013年到2022年苹果公司各产品&#xff08;iPhone、iPad、Mac等&#xff09;及服务的销售收入。iPhone是苹果公司销售收入最高的产品。 数据统计单位为&#xff1a;亿美元 。 数据说明&#xff1a; 数据整理自苹果公司历年10-K文件&#xff0c;每年10-K文件可能对之前年…

DP:两个数组的dp问题

解决两个数组的dp问题的常用状态表示&#xff1a; 1、选取第一个字符串[0-i]区间以及第二个字符串[0,j]区间作为研究对象 2、根据题目的要求确定状态表示 字符串dp的常见技巧 1、空串是有研究意义的&#xff0c;引入空串可以帮助我们思考虚拟的边界如何进行初始化。 2、如…

【odoo】odoo常用的ORM方法

概要 在Odoo中&#xff0c;ORM&#xff08;对象关系映射&#xff0c;Object-Relational Mapping&#xff09;方法是一种将Python对象映射到数据库表的方法。Odoo的ORM系统使开发者能够使用高级的Python代码而不是复杂的SQL语句来操作数据库。Odoo的ORM方法主要用于创建、读取、…

c#数组的使用

前言 我们在开发c#程序的过程中经常需要使用数组&#xff0c;这个数组就是用来存储多个值的一种数据类型。 1、一维数组 1.1 一维数组的声明 int[] array1;//数组的声明 1.2 一维数组的赋值 int[] array2 new int[] { 1, 2, 3, 3 };//数组的赋值 int[] array3 new int[…

云服务器Ubuntu系统的vim-plus(youcompleteme)完整安装

一. 安装vim-plus PS&#xff1a;需要在那个用户下配置vim-plus&#xff0c;就到那个用户下执行代码 git clone https://github.com/chxuan/vimplus.git ~/.vimplus cd ~/.vimplus ./install.sh二. 解决没有代码自动补全的问题 随便创建一个Test.cpp文件&#xff0c;vim打开…

图像生成新篇章:Stable Diffusion 3 Medium开源评析

摘要 在数字艺术与人工智能的交汇点上&#xff0c;Stable Diffusion 3&#xff08;SD3&#xff09;的开源无疑是一场技术革新的盛宴。就在3月份&#xff0c;我撰写了一篇博文&#xff0c;深入探讨了SD3的技术报告内容与介绍&#xff0c;文章发表在CSDN博客上&#xff0c;https:…

如何用多媒体沙盘实现智能交互体验?

随着多媒体技术在内容展示领域的迅猛进步&#xff0c;智能化信息交互方式已然跃升为公众瞩目的焦点&#xff0c;而展厅作为信息传递与产品展示的核心阵地&#xff0c;正面临着提升交互体验、强化信息传递效果的迫切需求。因此&#xff0c;以多媒体沙盘、LED屏幕等创新装置为媒介…

C/C++图形渲染引擎开发方向有钱景吗?

在当前的技术环境下&#xff0c;特别是在图形渲染引擎开发领域&#xff0c;的确存在一些挑战和变化。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频 讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私…