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。我已经修改了答案-使用可序列化事务。