小编Ell*_*urn的帖子

并发事务导致竞争条件对插入具有唯一约束

我有一个 Web 服务(http api),它允许用户安静地创建资源。在身份验证和验证之后,我将数据传递给 Postgres 函数,并允许它检查授权并在数据库中创建记录。

我今天发现了一个错误,即在同一秒内发出了两个 http 请求,导致使用相同的数据两次调用此函数。函数内部有一个子句,它在表上进行选择以查看值是否存在,如果存在,则获取 ID 并在下一个操作中使用该 ID,如果不存在,则插入数据,获取返回 ID,然后在下一个操作中使用它。下面是一个简单的例子。

select id into articleId from articles where title = 'my new blog';
if articleId is null then
    insert into articles (title, content) values (_title, _content)
    returning id into articleId;
end if;
-- Continue, using articleId to represent the article for next operations...
Run Code Online (Sandbox Code Playgroud)

正如您可能猜到的那样,我对数据进行了幻读,其中两个事务都进入了if articleId is null then块并试图插入到表中。一个成功了,另一个失败了,因为一个领域的独特限制。

我已经环顾四周,看看如何抵御这种情况,并找到了一些不同的选择,但由于某些原因,它们似乎都不适合我们的需求,我正在努力寻找任何替代方案。

  1. insert ... on conflict do nothing/update...我首先查看了on conflict看起来不错的选项,但是唯一的选项是do nothing不返回导致冲突的记录的 ID,并且do update不会工作,因为它会导致触发器在实际数据时被触发没有改变。在某些情况下,这不是问题,但在许多情况下,这可能会使会话用户会话无效,这是我们无法做到的。 …

postgresql concurrency transaction plpgsql upsert

14
推荐指数
2
解决办法
1万
查看次数

标签 统计

concurrency ×1

plpgsql ×1

postgresql ×1

transaction ×1

upsert ×1