我正在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
上具有UNIQUE约束。
通常,一切正常,但很少,大约每千次插入一次,触发器将返回错误“表的infotable
的重复键值违反了唯一约束” unique_col1_and_col2”。触发功能中有IF NOT EXISTS
部分,因此不应该发生。
第一个问题是这可能是什么原因?我唯一能想到的是两个用户同时获取相同信息的比赛,都触发了触发器,但随后一个人通过触发器更新了第二张表,而第二个用户则得到了重复错误。因此,他的整个插入查询都会失败,包括对主table
的插入。
如果是这种情况,我该怎么办?对于应该有100个以上的用户同时插入数据的表,使用插入锁定是个好主意吗?
如果是的话,我应该使用哪种类型的锁以及我应该锁定哪种表-主表或由触发器修改的第二个表? (或者我猜我应该在主插入语句中还是在触发器函数中拥有锁?)
答案 0 :(得分:1)
是的,这是比赛条件。同时运行的两个这样的触发器不会看到彼此的修改,因为事务尚未提交。
由于您对infotable
有唯一的约束,因此可以简单地使用
INSERT INTO infotable ...
ON CONFLICT (col1, col2) DO NOTHING;