【问题标题】:PostgreSQL triggers stopped workingPostgreSQL 触发器停止工作
【发布时间】:2015-11-17 00:08:14
【问题描述】:

我不得不重新安装我的 Hyper-V Windows 服务器,所以我对我的 PostgreSQL 数据库进行了架构备份。

之后,我导入了架构备份。从表面上看,一切都很好。所有的表、函数、触发器和序列都在那里。除了由于某种原因触发器函数不再做任何事情。

我有两个触发器,这是其中之一。

    CREATE TRIGGER t_update_modified
      AFTER UPDATE
      ON queue
      FOR EACH ROW
      EXECUTE PROCEDURE update_modified();

    CREATE OR REPLACE FUNCTION update_modified()
      RETURNS trigger AS
    $BODY$BEGIN
        NEW.modified = now();
        Return NEW;
    END;$BODY$
      LANGUAGE plpgsql VOLATILE
      COST 100;
    ALTER FUNCTION update_modified()
      OWNER TO postgres;
    GRANT EXECUTE ON FUNCTION update_modified() TO postgres;
    REVOKE ALL ON FUNCTION update_modified() FROM public;

我在代码中添加了RAISE WARNINGstatements 以检查函数是否实际执行以及它们执行了多远,我确认这些函数确实已执行并且它们一直执行到RETURN 语句。

我还添加了EXCEPTION 语句来捕获任何可能被抛出的异常,但没有这样的事情发生。

上面的函数应该更新修改的列的时间戳,但没有任何反应。我的两个触发器函数都曾经在旧虚拟机上工作。 postgres用户拥有该表的所有权限,并拥有触发函数的执行权限。

这是第二个触发器:

    CREATE TRIGGER t_new_task
      AFTER INSERT OR UPDATE OF status
      ON queue
      FOR EACH ROW
      EXECUTE PROCEDURE new_task();

    CREATE OR REPLACE FUNCTION new_task()
      RETURNS trigger AS
    $BODY$BEGIN
        NOTIFY newtask;
        RETURN NULL;
    END;$BODY$
      LANGUAGE plpgsql VOLATILE LEAKPROOF
      COST 100;
    ALTER FUNCTION new_task()
      OWNER TO postgres;
    GRANT EXECUTE ON FUNCTION new_task() TO postgres;
    GRANT EXECUTE ON FUNCTION new_task() TO public;

像之前一样,NOTIFY什么都不做。连接的客户端不会收到任何通知。这也曾经在旧虚拟机上工作。

与触发器函数相关的任何内容都不会记录到日志文件中,除非我向它们添加 RAISE WARNING 语句。

我以前从未遇到过此类触发器问题。有人知道这里发生了什么吗?

我也确实重新创建了这些触发器,但这也没有解决问题。

更新:我创建了一个新数据库,只是为了测试触发器。触发器在那里也不起作用,所以这个问题影响了整个 PostgreSQL 服务器。我已经准备好拔头发了。

更新 2:重新安装 PostgreSQL 服务器并删除其数据。触发器仍然不起作用。

【问题讨论】:

  • 配置项set log_min_messages = NOTIFY;
  • 实际上是notice,但是执行触发器时没有记录任何内容。好吧,除非我添加 RAISE WARNING 语句。

标签: postgresql


【解决方案1】:

使用 BEFORE 触发器。在 AFTER 触发器中,修改行值为时已晚。 如果您认为它以前有效并且这是环境问题,那么您很可能在某些时候对结果进行了混淆,因为(正如您在更新中提到的那样),这是一个普遍的事情。

这是手册中提到的方式,在 http://www.postgresql.org/docs/current/static/trigger-definition.html

返回值被忽略后触发的行级触发器 操作,因此它们可以返回 NULL。

BEFORE/AFTER 的更完整比较如下几段之后:

通常,行级 BEFORE 触发器用于检查或 修改将要插入或更新的数据。例如,一个 BEFORE 触发器可用于将当前时间插入到 时间戳列,或检查该行的两个元素是否 持续的。行级 AFTER 触发器最明智地用于 将更新传播到其他表,或进行一致性检查 针对其他表。这种分工的原因是 AFTER 触发器可以确定它看到的是行的最终值, 而 BEFORE 触发器不能;可能还有其他 BEFORE 触发器 在它之后射击。如果您没有特定的理由触发 BEFORE 或 AFTER,BEFORE 情况更有效,因为 有关操作的信息不必保存到结束 声明

【讨论】:

  • 如你所见,我有两个函数。 BEFORE 是时间戳触发器应该使用的,而 AFTER 是通知触发器应该使用的。由于我一直试图让它们工作,我必须将时间戳触发器保留为 AFTER。无论如何,不​​幸的是这并没有解决问题。无论是 BEFORE 还是 AFTER,这两个触发器都不会按预期工作。
  • @KeeperB5:请更新您的问题以反映您的更改。就像现在一样,它是一个 after 更新或插入触发器,因此对 NEW 的更改将被忽略,如文档所述。
  • 睡了一夜好觉后,我又看了看这个。我三重检查了t_update_modified 使用BEFORE UPDATEt_new_task 使用AFTER INSERT OR UPDATE。你瞧,现在触发器起作用了。尽管我本可以发誓,在我开始弄乱它们以解决问题之前,触发器就是这样设置的。无论如何,现在一切都很好,我将接受您的回答作为解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-10
  • 2020-04-25
  • 1970-01-01
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多