我正在尝试了解将哪种类型的锁用于触发功能。
简化的功能:
CREATE OR REPLACE FUNCTION max_count() RETURNS TRIGGER AS
$$
DECLARE
max_row INTEGER := 6;
association_count INTEGER := 0;
BEGIN
LOCK TABLE my_table IN ROW EXCLUSIVE MODE;
SELECT INTO association_count COUNT(*) FROM my_table WHERE user_id = NEW.user_id;
IF association_count > max_row THEN
RAISE EXCEPTION 'Too many rows';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE CONSTRAINT TRIGGER my_max_count
AFTER INSERT OR UPDATE ON my_table
DEFERRABLE INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE max_count();
我最初打算使用 EXCLUSIVE
但感觉太重了。我真正想要的是确保在此函数执行期间没有新行添加到具有相关 user_id
的表中。
最佳答案
如果要防止并发事务修改表,SHARE
锁将是正确的。但是,如果两个这样的事务同时运行,这可能会导致死锁——每个都修改了一些行,并在尝试升级表锁时被另一个阻塞。
此外,所有与SHARE UPDATE EXCLUSIVE
冲突的表锁都将导致autovacuum取消,当这种情况发生太频繁时会导致表膨胀。
所以远离表锁,它们通常是错误的。
解决此问题的更好方法是完全不使用显式锁定,而是对访问此表的所有事务使用 SERIALIZABLE
隔离级别。
然后你可以简单地使用你的触发器(没有锁),并且不会发生异常。如果出现序列化错误,请重复事务。
这会带来一定的性能损失,但比表锁允许更多的并发性。它还避免了开头描述的问题。
关于postgresql - 哪个显式锁用于触发器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55653461/