Postgresql 触发器有时会因重复密钥错误而失败

Postgresql 触发器有时会因重复密钥错误而失败,postgresql,triggers,race-condition,Postgresql,Triggers,Race Condition,我正在AWS中使用PostgreSQL RDS实例。基本上,有一个将数据插入第一个表的查询,我们称之为table。那里的数据在某些字段中可能有重复项(主键除外) 然后是更新另一个表的触发器,infotable,不允许重复 触发因素: CREATE TRIGGER insert_infotable AFTER INSERT ON table FOR EACH ROW EXECUTE PROCEDURE insert_infotable(); 触发器功能的相关部分如下所示: CREATE

我正在AWS中使用PostgreSQL RDS实例。基本上,有一个将数据插入第一个表的查询,我们称之为
table
。那里的数据在某些字段中可能有重复项(主键除外)

然后是更新另一个表的触发器,
infotable
,不允许重复

触发因素:

CREATE TRIGGER insert_infotable AFTER INSERT ON table
    FOR EACH ROW EXECUTE PROCEDURE insert_infotable();
触发器功能的相关部分如下所示:

CREATE OR REPLACE FUNCTION insert_infotable() RETURNS trigger AS $insert_infotable$
    BEGIN   
        --some irrelevant code
        IF NOT EXISTS (SELECT * FROM infotable WHERE col1 = NEW.col1 AND col2 = NEW.col2) THEN
            INSERT INTO infotable(col1, col2, col3, col4, col5, col6) values (--some values--);
        END IF;
        RETURN NEW;
    END;
$insert_infotable$ LANGUAGE plpgsql;
infotable
对列
col1
col2
具有唯一的约束

一般来说,所有操作都正常,但很少,大约每1k次插入,触发器会返回一个错误“重复键值违反了表
infotable
的唯一约束“unique\u col1\u和\u col2”。这不应该发生,因为触发器函数中存在
IF NOT existed
部分

第一个问题是,这可能是什么原因?我唯一能想到的是两个用户同时获得相同信息的比赛,两个用户都触发触发器,但一个用户通过触发器更新第二个表,第二个用户得到重复错误。因此,他的整个insert查询失败,包括对主
表的insert

如果是这样,我能做些什么?对于一个应该有100多个用户同时插入数据的表,使用insert锁是一个好主意吗


如果是,我应该使用什么类型的锁?我应该锁定什么表?主表还是第二个被触发器修改的表?(或者我想我应该在主insert语句中使用锁还是在触发器函数中使用锁?

是的,这是一个竞争条件。同时运行的两个这样的触发器不会看到彼此的修改,因为事务尚未提交

由于对
infotable
有一个唯一的约束,因此只需使用

INSERT INTO infotable ...
ON CONFLICT (col1, col2) DO NOTHING;