Postgresql 触发器有时会因重复密钥错误而失败
我正在AWS中使用PostgreSQL RDS实例。基本上,有一个将数据插入第一个表的查询,我们称之为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
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;