gpt4 book ai didi

postgresql - PostgreSQL 中没有出现序列化访问错误,而应该是

转载 作者:行者123 更新时间:2023-11-29 13:15:35 25 4
gpt4 key购买 nike

我对 SERIALIZABLE 隔离级别行为在类似于下面描述的情况下的行为感到担忧。

表格:

CREATE TABLE concurrency_test (
id serial PRIMARY KEY,
sum INT NOT NULL
);

查询:

+------+-------------------------------------------------+-------------------------------------------------+
| Step | Connection #1 | Connection #2 |
+------+-------------------------------------------------+-------------------------------------------------+
| 1 | | START TRANSACTION ISOLATION LEVEL SERIALIZABLE; |
| 2 | | INSERT INTO concurrency_test (sum) VALUES(400); |
| 3 | START TRANSACTION ISOLATION LEVEL SERIALIZABLE; | |
| 4 | SELECT SUM("sum") FROM concurrency_test; | |
| 5 | | COMMIT; |
| 6 | INSERT INTO concurrency_test (sum) VALUES(300); | |
| 7 | COMMIT; | |
+------+-------------------------------------------------+-------------------------------------------------+

第 4 步SELECT 查询看不到另一个事务插入的新行,因为它尚未提交。因此,第 6 步 中的以下INSERT 查询依赖于陈旧数据。

我预计 SERIALIZABLE 隔离级别会解决这个问题,并且不允许我在第 7 步 成功提交事务并返回 40001 错误...但令我惊讶的是,它没有引发任何错误。

为什么会发生这种情况,我怎样才能实现我需要的行为?

最佳答案

第 4 步中的 SELECT 依赖陈旧数据,因为修改尚未提交。在事务提交之前,数据库就像什么都没发生一样。

这是由 READ COMMITTED 隔离级别和所有更高级别保证的。 (PostgreSQL 不允许脏读,因此即使您请求 READ UNCOMMITTED 隔离级别,您也会遇到此行为。)

此外,SERIALIZABLE 意味着所有事务的结果保证与事务的某些序列化执行的结果相同。这显然是这里的情况:如果我们通过在连接 #2 上执行事务之前在连接 #1 上执行事务来序列化,我们会得到相同的结果。

它永远不是必需的,但如果您想通过强制序列化执行来减少并发性,请在每个 START TRANSACTION 之后立即添加以下语句:

LOCK TABLE concurrency_test IN ACCESS EXCLUSIVE MODE;

关于postgresql - PostgreSQL 中没有出现序列化访问错误,而应该是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49553835/

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