gpt4 book ai didi

sql - 涉及子选择和外键的 Postgres 竞争条件

转载 作者:行者123 更新时间:2023-12-03 14:20:32 28 4
gpt4 key购买 nike

我们有 2 个表定义如下

CREATE TABLE foo (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE
);

CREATE TABLE bar (
foo_id BIGINT UNIQUE,
foo_name TEXT NOT NULL UNIQUE REFERENCES foo (name)
);

我注意到在同时执行以下两个查询时
INSERT INTO foo (name) VALUES ('BAZ')
INSERT INTO bar (foo_name, foo_id) VALUES ('BAZ', (SELECT id FROM foo WHERE name = 'BAZ'))
在某些情况下,最终可能会在 bar 中插入一行,其中 foo_idNULL 。这两个查询由两个完全不同的进程在不同的事务中执行。
这怎么可能?我希望第二条语句要么由于外键违规而失败(如果 foo 中的记录不存在),要么以 foo_id 的非空值成功(如果是)。
是什么导致了这种竞争条件?是由于子选择,还是由于检查外键约束的时间?
我们使用隔离级别“已提交读”和 postgres 10.3 版。
编辑
我认为这个问题并不清楚是什么让我感到困惑。问题是关于在执行单个语句期间如何以及为什么观察到数据库的 2 个不同状态。 subselect 观察到 foo 中的记录不存在,而 fk 检查认为它存在。如果只是没有规则阻止这种竞争条件,那么这本身就是一个有趣的问题 - 为什么不能使用事务 ID 来确保对两者都观察到相同的数据库状态?

最佳答案

INSERT INTO bar 中的子选择无法看到同时插入 foo 的新行,因为后者尚未提交。
但是到执行检查外键约束的查询时,INSERT INTO foo已经提交,所以外键约束不会报错。
解决此问题的一种简单方法是对 REPEATABLE READ 使用 INSERT INT bar 隔离级别。然后外键检查使用与 INSERT 相同的快照,它不会看到新提交的行,并且会抛出约束违规错误。

关于sql - 涉及子选择和外键的 Postgres 竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64068518/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com