您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

SELECT或INSERT函数是否易于出现竞争状况?

SELECT或INSERT函数是否易于出现竞争状况?

它的经常性问题 _ 下可能并发写入负载,涉及(但不同于)UPSERT(这是 INSERTUPDATE_)。

使用新的UPSERT实施INSERT ... ON CONFLICT .. DO UPDATE,我们可以大大简化。PL / pgsql函数INSERTSELECT一个 _ _ 行(标记):

CREATE OR REPLACE FUNCTION f_tag_id(_tag text, OUT _tag_id int) AS
$func$
BEGIN
   SELECT tag_id  -- only if row existed before
   FROM   tag
   WHERE  tag = _tag
   INTO   _tag_id;

   IF NOT FOUND THEN
      INSERT INTO tag AS t (tag)
      VALUES (_tag)
      ON     CONFLICT (tag) DO NOTHING
      RETURNING t.tag_id
      INTO   _tag_id;
   END IF;
END
$func$ LANGUAGE plpgsql;

比赛条件仍然有一个很小的窗口。为了 _ _ 您获得ID,请执行以下操作:

CREATE OR REPLACE FUNCTION f_tag_id(_tag text, OUT _tag_id int) AS
$func$
BEGIN
LOOP
   SELECT tag_id
   FROM   tag
   WHERE  tag = _tag
   INTO   _tag_id;

   EXIT WHEN FOUND;

   INSERT INTO tag AS t (tag)
   VALUES (_tag)
   ON     CONFLICT (tag) DO NOTHING
   RETURNING t.tag_id
   INTO   _tag_id;

   EXIT WHEN FOUND;
END LOOP;
END
$func$ LANGUAGE plpgsql;

这一直循环直到成功INSERT或失败为止SELECT。称呼:

SELECT f_tag_id('possibly_new_tag');

如果 同一事务中的 后续命令依赖于该行的存在,并且实际上其他事务可能同时更新或删除该行,则可以使用来锁定SELECT语句中的现有行FOR SHARE。 如果改为插入该行,则该行将一直锁定到事务结束为止。

如果大多数时间都插入了新行,则从开始开始INSERT使其更快。

SQL 2022/1/1 18:47:36 有428人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶