PostgreSQL 事件触发器设置

PostgreSQLBeginner
立即练习

介绍

在本实验中,你将学习如何在 PostgreSQL 中设置事件触发器。事件触发器会捕获数据定义语言 (DDL) 事件,例如创建、修改或删除数据库对象。

你将创建一个专门的日志表和一个特殊函数来记录这些事件。然后,你将创建一个事件触发器,该触发器在 CREATE TABLE 命令之后触发,记录新表的详细信息。这个实践练习将指导你创建必要的组件,测试触发器的功能,并在之后清理数据库对象。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 91%。获得了学习者 71% 的好评率。

创建日志表和触发器函数

在此步骤中,你将创建记录 DDL 事件所需的数据库对象:一个用于存储日志的表和一个触发器将执行的函数。

首先,打开终端并使用 psql 交互式 shell 连接到 PostgreSQL 数据库。你将在该 shell 中执行后续的 SQL 操作。

sudo -u postgres psql

现在你应该会看到 PostgreSQL 提示符,它看起来像 postgres=#

接下来,创建一个名为 event_log 的表来存储每个 DDL 事件的详细信息。该表将包含事件时间、类型、模式(schema)、对象名称以及已执行命令的列。

psql shell 中执行以下 SQL 命令:

CREATE TABLE event_log (
    event_time timestamp with time zone,
    event_type text,
    schema_name text,
    object_name text,
    command_tag text
);

成功执行后,PostgreSQL 将响应:

CREATE TABLE

现在,创建将由 DDL 事件触发的函数。此函数 log_ddl_event 将向 event_log 表插入一条新记录。

CREATE OR REPLACE FUNCTION log_ddl_event()
RETURNS event_trigger
AS $$
BEGIN
    INSERT INTO event_log (event_time, event_type, schema_name, object_name, command_tag)
    SELECT now(), tg_event, ddl_command.schema_name, ddl_command.objid::regclass, tg_tag
    FROM pg_event_trigger_ddl_commands() AS ddl_command;
END;
$$ LANGUAGE plpgsql;

让我们分解一下这个函数:

  • RETURNS event_trigger: 指定这是一个专门用于事件触发器的特殊类型的函数。
  • AS $$ ... $$ LANGUAGE plpgsql: 使用 plpgsql 过程语言定义函数体。
  • INSERT INTO event_log ...: 这是核心操作,它向我们的日志表插入一行新数据。
  • now(): 一个标准函数,返回当前时间戳。
  • tg_event, tg_tag: 在触发器函数内部可用的特殊变量,提供有关事件的上下文信息,例如 ddl_command_endCREATE TABLE
  • pg_event_trigger_ddl_commands(): 一个返回描述已执行 DDL 命令的行集的函数。我们使用它来获取正在创建的对象的 schema_nameobjid(对象标识符)。

运行命令后,你将看到以下确认信息:

CREATE FUNCTION

你现在已成功设置了事件触发器的基础组件。

创建 DDL 事件触发器

在日志表和函数就绪后,你现在可以创建事件触发器本身了。此触发器将监视特定的 DDL 命令,并在它们发生时执行你的日志记录函数。

在同一个 psql shell 中,执行以下命令来创建一个名为 log_table_creation 的事件触发器:

CREATE EVENT TRIGGER log_table_creation
ON ddl_command_end
WHEN TAG IN ('CREATE TABLE')
EXECUTE FUNCTION log_ddl_event();

让我们来分析一下这个语句的组成部分:

  • CREATE EVENT TRIGGER log_table_creation: 这为你的新事件触发器命名。
  • ON ddl_command_end: 这指定了触发器的时间点。它将在 DDL 命令执行完成后触发。
  • WHEN TAG IN ('CREATE TABLE'): 这是一个过滤条件。只有当命令标签匹配 CREATE TABLE 时,触发器才会激活。你也可以在这里添加其他标签,如 ALTER TABLEDROP TABLE
  • EXECUTE FUNCTION log_ddl_event(): 这指定了当触发器的条件满足时要运行的函数。

执行命令后,PostgreSQL 将确认其创建:

CREATE EVENT TRIGGER

你的事件触发器现在已激活,并将记录每一次新的表创建。

测试事件触发器

现在是时候测试事件触发器是否按预期工作了。你将创建一个新表,然后检查 event_log 表以查看创建事件是否已被记录。

首先,创建一个名为 employees 的简单表:

CREATE TABLE employees (
    id serial PRIMARY KEY,
    name text NOT NULL
);

CREATE TABLE 命令将正常执行,你将看到标准的确认信息:

CREATE TABLE

在后台,此操作应该已经触发了你的 log_table_creation 触发器。为了验证这一点,请查询 event_log 表以查看其内容:

SELECT schema_name, object_name, command_tag FROM event_log;

输出将显示多条记录。这是因为使用 serial PRIMARY KEY 创建表时,还会隐式创建序列 (sequence) 和主键约束 (primary key constraint)。事件触发器会捕获所有相关的 DDL 命令,从而在日志中产生多条条目。

 schema_name |   object_name    | command_tag
-------------+------------------+--------------
 public      | employees_id_seq | CREATE TABLE
 public      | employees        | CREATE TABLE
 public      | employees_pkey   | CREATE TABLE
 public      | employees_id_seq | CREATE TABLE
(4 rows)

此结果证实了你的事件触发器正在正常运行,并记录了表创建及其依赖对象的事件。

清理数据库对象

移除不再需要的数据库对象是一种良好的实践。在最后一步,你将删除在此次实验中创建的事件触发器、表和函数。

首先,删除事件触发器:

DROP EVENT TRIGGER log_table_creation;

你将看到确认消息:

DROP EVENT TRIGGER

接下来,删除你创建的两个表 employeesevent_log

DROP TABLE employees;
DROP TABLE event_log;

PostgreSQL 将确认每个操作:

DROP TABLE
DROP TABLE

最后,删除触发器函数:

DROP FUNCTION log_ddl_event();

你将看到最终确认信息:

DROP FUNCTION

你现在已成功清理了在此次实验中创建的所有对象。要退出 psql shell 并返回到常规终端提示符,请输入 \q 并按 Enter 键。

\q

总结

在此次实验中,你学习了如何在 PostgreSQL 中实现事件触发器来监控 DDL 活动。你创建了一个日志表来存储事件数据,并创建了一个 PL/pgSQL 函数来填充它。然后,你定义了一个事件触发器,该触发器专门捕获 CREATE TABLE 事件,并将其与你的日志函数关联起来。通过测试触发器并验证日志条目,你获得了关于这些组件如何协同工作的实践经验。最后,你通过清理创建的触发器、表和函数,练习了良好的数据库管理实践。