gpt4 book ai didi

postgresql - 运行更新时 PostgreSQL 中的死锁

转载 作者:行者123 更新时间:2023-11-29 11:07:57 26 4
gpt4 key购买 nike

阅读有关 PostgreSQL 死锁的内容时,我有点困惑。

一个典型的死锁例子是:

-- Transaction 1
UPDATE customer SET ... WHERE id = 1
UPDATE customer SET ... WHERE id = 2

-- Transaction 2
UPDATE customer SET ... WHERE id = 2
UPDATE customer SET ... WHERE id = 1

但是如果我按如下方式更改代码会怎样:

-- Transaction 1
UPDATE customer SET ... WHERE id IN (1, 2)

-- Transaction 2
UPDATE customer SET ... WHERE id IN (1, 2)

这里会不会有死锁的可能?

基本上我的问题是:在第二种情况下,PostgreSQL 是逐行锁定行,还是锁定 WHERE 条件覆盖的整个范围?

提前致谢!

最佳答案

在 PostgreSQL 中,行在更新时将被锁定——事实上,这实际工作的方式是每个元组(行的版本)都有一个名为 xmin 的系统字段来指示哪个事务使该元组成为当前元组(通过插入或更新)和一个名为 xmax 的系统字段来指示哪个事务使该元组过期(通过更新或删除)。当您访问数据时,它会检查每个元组以确定它是否对您的事务可见,方法是根据这些值检查您的事件“快照”。

如果您正在执行更新并且与您的搜索条件匹配的元组有一个 xmin 可以使它对您的快照可见,并且有一个事件事务的 xmax,它会阻塞,等待该事务完成。如果首先更新元组的事务回滚,您的事务将唤醒并处理该行;如果第一个事务提交,您的事务就会唤醒并根据当前事务隔离级别采取行动。

显然,死锁是这种情况发生在不同顺序的行的结果。 RAM中没有可以同时获得所有行的行级锁,但是如果行以相同的顺序更新,则无法获得循环锁定。不幸的是,建议的 IN(1, 2) 语法并不能保证这一点。不同的 session 可能有不同的成本因素处于事件状态,后台“分析”任务可能会在一个计划和另一个计划的生成之间更改表的统计信息,或者它可能正在使用 seqscan 并受到 PostgreSQL 优化的影响,这会导致新的 seqscan加入一个已经在进行中的并“循环”以减少磁盘 I/O。

如果您在应用程序代码中或使用游标以相同的顺序一次更新一个,那么您只会遇到简单的阻塞,而不会出现死锁。不过,一般来说,关系数据库容易出现序列化失败,最好通过一个框架访问它们,该框架将基于 SQLSTATE 识别它们并从一开始就自动重试整个事务。在 PostgreSQL 中,序列化失败的 SQLSTATE 始终为 40001 或 40P01。

http://www.postgresql.org/docs/current/interactive/mvcc-intro.html

关于postgresql - 运行更新时 PostgreSQL 中的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10245560/

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