如何在postgresql中以弹性方式删除触发器

时间:2014-07-14 14:02:55

标签: postgresql triggers

我希望删除当前正在生产的触发器,因为它不再需要,但问题是当我尝试最简单的方法时,这就像

drop trigger <triggername> on <tablename>

它造成巨大的桌锁,一切都冻结了!

触发器的作用是:

插入或更新行时,检查字段的内容,拆分并填充另一个表。

我应该如何在不造成生产环境麻烦的情况下立即禁用(并在之后删除)?

提前致谢并抱歉我的英语;)

1 个答案:

答案 0 :(得分:9)

你可以尝试ALTER TABLE ... DISABLE TRIGGER - 但它需要相同的锁定力量,所以我不认为它会给你带来更多好处。

PostgreSQL 9.4中的工作使得ALTER TABLE对某些操作采取较弱的锁定。这可能会有所帮助。

与此同时,我CREATE OR REPLACE FUNCTION用简单的无操作功能替换触发器。

然后,为了实际放下触发器,我可能会写一个脚本:

BEGIN;
LOCK TABLE the_table IN ACCESS EXCLUSIVE MODE NOWAIT;
DROP TRIGGER ...;
COMMIT;

如果有人使用该表,脚本将在LOCK TABLE中止。

然后我会循环运行直到成功。

如果这不起作用(如果表总是忙)但是如果大多数交易真的很短,我可能会尝试LOCK TABLE没有NOWAIT,但设置一个简短的statement_timeout。所以脚本应该是这样的:

BEGIN;
SET LOCAL statement_timeout = '5s';
LOCK TABLE the_table IN ACCESS EXCLUSIVE MODE NOWAIT;
DROP TRIGGER ...;
COMMIT;

如果它无法及时完成工作,那么可以确保通过失败来实现相当短暂的中断。再次,我会定期运行它,直到它成功。

如果这两种方法都没有效果 - 比如,由于大量长期交易 - 我可能只是接受了将其锁定一段时间的需要。我启动了drop trigger然后我{d} pg_terminate_backend所有持有表锁的并发事务,因此他们的连接被丢弃并且他们的事务终止了。这让drop trigger迅速进行,代价是更大的干扰。如果您的应用程序编写得很好,您只能考虑这样的方法,以便他们只是在连接丢失等瞬态错误上重试事务。

另一种可能的方法是通过直接修改系统目录来禁用(而不是删除)触发器。