防止 Postgres 中的竞争条件

Prevent race condition in Postgres

假设我有一个端点/seen/{bigint_number}, 大约 10K 并发访问一个随机 bigint 数。

逻辑很简单。如果该号码已经存储在数据库中,则 returns true,如果该号码尚未存储,则已存储并且 returns .

逻辑首先是“select * from myTable where number = bigint_number”如果找到 return true,否则 插入 table.

当同一个并发用户具有相同的号码时,竞争条件就在这里。

我们如何避免这种情况?

我相信您正在寻找的是 UPSERT 操作: https://wiki.postgresql.org/wiki/UPSERT

你为什么害怕竞争条件?数据库有一套工具,如事务和锁来帮助您解决这些问题。

您需要对 number 列进行唯一约束。

然后你可以这样进行:

WITH x AS (
   INSERT INTO mytable (number) VALUES (12346)
   ON CONFLICT (number) DO NOTHING
   RETURNING number
)
SELECT count(number) = 0
FROM x;

如果插入一行,INSERT 语句将 return 一行,因此在这种情况下查询将 return FALSE

这没有竞争条件,因为 INSERT ... ON CONFLICT 是。