防止 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
是。
假设我有一个端点/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
是。