2014-07-14 25 views
5

删除了触发器以弹性的方式我在寻找一个目前在生产触发下降,因为它不再是必要的,但问题是,当我尝试最简单的方式,这是一样的东西如何在PostgreSQL的

drop trigger <triggername> on <tablename> 

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

什么触发的作用是:

当行被插入或更新,检查一个字段的内容,将它和填充另一个表。

我应该如何立即停用(并在此后放弃),而不会在生产环境中造成麻烦?

在此先感谢和我的英语很抱歉;)

回答

7

你可以尝试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然后我会pg_terminate_backend所有并发交易,持有表上的锁,使他们的连接下降,他们的交易终止。这会让drop trigger迅速进行,代价是更大的中断。如果你的应用程序编写得很好,你只能考虑这种方法,这样他们只会在连接丢失等瞬时错误时重试事务。

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

+3

我想你的第二个SQL语句中的NOWAIT是一个错误。 –

+0

不错,非常感谢您的完整答案!我会尽快尝试,但所提供的信息很棒,包含了我需要的方法!真棒! – Krynble

+0

只需添加一个便条,我就可以运行查询,它的功能就像一个魅力!即时下降触发器完全弹性!非常感谢! – Krynble