Postgresql 触发器使用哪个显式锁?
我试图了解触发器函数使用哪种类型的锁 简化功能:Postgresql 触发器使用哪个显式锁?,postgresql,locking,database-trigger,database-concurrency,Postgresql,Locking,Database Trigger,Database Concurrency,我试图了解触发器函数使用哪种类型的锁 简化功能: 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 associatio
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();
我最初打算使用
独家
,但感觉太沉重了。我真正想要的是确保在执行此函数期间,不会向表中添加具有相关user\u id
的新行。如果要防止并发事务修改表,则共享
锁是正确的。但是,如果两个这样的事务同时运行,那么这可能会导致死锁——每个事务都修改了一些行,并且在试图升级表锁时被另一个事务阻塞
此外,所有与共享更新独占性冲突的表锁将导致自动真空取消,这将在频繁发生时导致表膨胀
所以远离桌子锁,它们通常是错误的
更好的方法是根本不使用显式锁定,而是对访问此表的所有事务使用SERIALIZABLE
隔离级别
然后您可以简单地使用触发器(无锁),并且不会发生异常。如果出现序列化错误,请重复该事务
这会带来一定的性能损失,但允许比表锁更多的并发性。它还避免了开头描述的问题。它引发了PG::FeatureNotSupported:ERROR:FOR UPDATE不允许使用聚合函数
Hey,question,它将锁定这些行,但是如何不允许使用该选择标准为创建记录?目标是为给定参数(用户id)锁定添加新条目,然后计算关联计数
,并确保其不超过allowedTrue。我已经修改了答案-使用可序列化事务。