如何仅在一个事务中禁用 PostgreSQL 触发器?

Posted

技术标签:

【中文标题】如何仅在一个事务中禁用 PostgreSQL 触发器?【英文标题】:How to disable PostgreSQL triggers in one transaction only? 【发布时间】:2016-10-10 09:30:45 【问题描述】:

我需要在事务中临时禁用一个 PostgreSQL 触发器,但没有硬锁定表。有人知道这是否可能吗?

类似这样的事情,没有锁定表和禁用此事务之外的触发器。

BEGIN TRANSACTION;

  ALTER TABLE foo DISABLE TRIGGER bar;

  -- DO SOME UPDATES ON foo
  UPDATE foo set field = 'value' where field = 'test';

  ALTER TABLE foo ENABLE TRIGGER bar;

COMMIT;

【问题讨论】:

【参考方案1】:

您可以在此表中禁用所有触发器。它应该是这样的:

ALTER TABLE tblname DISABLE TRIGGER USER;
Your SQL;
ALTER TABLE tblname ENABLE TRIGGER USER;

要禁用单个触发器,请使用:

ALTER TABLE tblname DISABLE TRIGGER trigger_name;
Your SQL;
ALTER TABLE tblname ENABLE TRIGGER trigger_name;

您可以在文档中阅读有关 ALTER TABLE 的更多信息。

【讨论】:

是的,但我希望它只在一个 sql 事务中被禁用,并且不想在触发器被禁用时阻止表。 DISABLE TRIGGER : 在事务中硬锁表 这不能回答 gori 的问题。他和我需要在不锁定桌子的情况下禁用触发器。假设我的交易需要 60 秒并且触发器被禁用。桌子将被锁定,这在生产中是不可接受的。【参考方案2】:

要暂时禁用 PostgreSQL 会话中的所有触发器,请使用以下命令:

SET session_replication_role = replica;

仅禁用当前数据库会话的所有触发器。对批量操作很有用,但请记住要小心保持数据库的一致性。

重新启用:

SET session_replication_role = DEFAULT;

来源:http://koo.fi/blog/2013/01/08/disable-postgresql-triggers-temporarily/

【讨论】:

SET session_replication_role = replica; 最终会锁定表吗? 回答我自己的问题似乎不是【参考方案3】:

我遇到了同样的问题,并想出了一个聪明而干净的方法来解决它。

首先,如果触发器是您当前正在执行的触发器,则您不能禁用触发器。那是我的场景——我插入到一个表中是因为插入它——否则会导致触发器的无限循环。

我解决它的方法是在混合中添加一个局部参数变量,该变量基本上充当全局变量,当触发器已经被使用时,它将禁用触发器的进一步调用。

为此,请在触发器函数的最开始添加以下代码:

SET LOCAL your.variable_name to 'TRUE';

然后(假设您使用 pg ≥ 9.6)您只需将以下行添加到您的CREATE TRIGGER

WHEN (current_setting('your.variable_name', 't') <> 'TRUE')

我没有做过任何基准测试,但根据我之前的经验,我希望它非常高效。

【讨论】:

要禁用触发器链接,您可以查看堆栈深度 - 查看 pg_trigger_depth() 函数 我不得不稍微调整一下:when (coalesce(current_setting('pokko.loading'::text, true), 'FALSE') <> 'TRUE'::text) 从 9.2 开始,Amit 是正确的,pg_trigger_depth() 可能是更本地和更合适的解决方案。我还没有测试过,但我相信这也能正常工作。

以上是关于如何仅在一个事务中禁用 PostgreSQL 触发器?的主要内容,如果未能解决你的问题,请参考以下文章

仅在事务完成后触发 post_save 信号

用于禁用/启用触发所有的 Postgresql 权限

Postgresql 学习记录,模式,分区表,触发器,事务,窗口函数,视图,建表,约束等

如何禁用按钮的 Enter 键

在 PostgreSQL 中的表上禁用 DELETE?

双击ActiveX控件时如何禁用Visual Basic对话框