Postgres 触发器和行锁定

Postgres trigger and row locking

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

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

BEGIN;
INSERT INTO table_a VALUES (record1) , (record2), (record3)………;
INSERT INTO table_a VALUES (record91) , (record92), (record93)………;
…..
….
COMMIT;

一次insert可以有几百条记录,COMMIT之间可以有几十条INSERT语句

Table_a 上有一个触发器定义为...。

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

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

中更新

我有第二个进程也尝试(偶尔)更新 table_b 中的记录。在极少数情况下,它可能会尝试更新批量进程正在更新 table_b 中的同一行

问题 – 批量插入语句中的任何内容是否会影响我的第二个进程能够更新 table_b 中的记录?我知道批量插入过程每次更新table_b中的行时都会获得一个行锁,但是什么时候释放那个行锁呢? – 何时插入单个记录(record1、record2、record3 等)?或者整个 INSERT 语句何时完成?或者什么时候达到 COMMIT?

更多信息 - 我提出这个问题的总体目的是试图理解为什么我的第二个进程在尝试更新 [=] 中的行时偶尔会暂停一分钟或更长时间58=] 也由批量加载进程更新。 似乎 正在发生的是 table_b 中的目标记录上的锁定在 COMMIT 被执行之前实际上并没有被释放达到 - 这与我认为应该发生的事情相反。 (我认为应该在该行的 UPDATE 完成后立即释放行锁)


回答后更新 - 是的,当然你们都是对的。在我看来,我以某种方式说服自己在触发器中执行的个别更新与整个事务的整体 BEGIN 和 COMMIT 在某种程度上是分开的。傻我。

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

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

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