Postgres触发器和行锁定

时间:2018-11-01 21:42:30

标签: postgresql locking database-trigger

请帮助我理解触发器和锁如何相互作用

我用类似这样的语句将记录批量加载到表中……..

AFTER INSERT ON table_a FOR EACH ROW EXECUTE PROCEDURE foo();

在一个插入中可以有数百条记录,并且在COMMIT之间可以有几十条INSERT语句

Table_a的触发器定义为…。

{{1}}

过程 foo()在添加新行时对其进行解析,并将(以及其他内容)更新摘要 table_b 中的记录(由主键唯一标识) )。因此,对于插入到 table_a 中的每条记录,相应的记录将在 table_b

中进行更新

我有第二个过程,该过程还会尝试(偶尔)更新 table_b 中的记录。在极少数情况下,它可能会尝试更新 table_b 中与批量处理过程相同的行

问题 –批量插入语句中的任何内容是否会影响我的第二个进程能够更新 table_b 中的记录?我知道批量插入过程每次在 table_b 中更新一行时都会获得行锁,但是何时释放该行锁? –当插入单个记录(记录1,记录2,记录3等)时?还是当整个INSERT语句完成时?还是到达COMMIT时?

更多信息-我对这个问题的总体目的是试图了解为什么我的第二个过程在尝试更新table_b中的行时偶尔会暂停一分钟或更长时间,而该行也正在被更新批量加载过程。 似乎正在发生的事情是,直到到达COMMIT才真正释放对 table_b 中目标记录的锁定-这与我认为应该的相反即将发生。 (我认为应该在该行的UPDATE完成后立即释放行锁)


在回答后进行更新-是的,您当然是对的。在我心中,我以某种方式使自己确信,触发器内执行的各个更新与整个事务的整体BEGIN和COMMIT有所不同。愚蠢的我。

引入了使用一个INSERT添加多个记录以及在COMMIT之间添加多个INSERT的做法,以提高批量加载速度(确实如此),我忘记了增加释放锁之前的时间的副作用。 / p>

1 个答案:

答案 0 :(得分:1)

回滚事务时会发生什么?很显然,应该回滚table_a,上的所有插入以及table_b,上的所有更新。这就是为什么由触发器更新的table_b的所有行都将被锁定,直到事务完成。

在每个insert之后进行提交(减少单个事务中插入的行数)将减少与并发进程发生冲突的机会。