加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

运行UPDATE时PostgreSQL中的死锁

发布时间:2020-12-13 16:28:41 所属栏目:百科 来源:网络整理
导读:阅读有关PostgreSQL死锁的一点点困惑. 一个典型的僵局的例子是: -- Transaction 1UPDATE customer SET ... WHERE id = 1UPDATE customer SET ... WHERE id = 2-- Transaction 2UPDATE customer SET ... WHERE id = 2UPDATE customer SET ... WHERE id = 1
阅读有关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的系统字段来指示哪个事务已过期该元组(通过更新或删除).当您访问数据时,它会检查每个元组,以确定它是否对您的事务可见,通过根据这些值检查您的活动“快照”.

如果您正在执行UPDATE,并且与您的搜索条件匹配的元组具有xmin,这将使您的快照和活动事务的xmax可见,它将阻止等待该事务完成.如果首次更新元组的事务回滚,则您的事务将唤醒并处理该行;如果第一个事务提交,您的事务将唤醒并根据当前事务隔离级别执行操作.

显然,这种情况的发生是以不同顺序排列的.在RAM中没有可以同时获取所有行的行级锁定,但是如果行以相同的顺序更新,则不能进行循环锁定.不幸的是,建议的IN(1,2)语法不能保证.不同的会话可能具有不同的成本因素的活动,背景“分析”任务可能会改变在生成一个计划和另一个计划之间的表的统计信息,或者可能使用seqscan并受到PostgreSQL优化的影响,这导致新的排序加入一个已经进行中的“循环”来减少磁盘I / O.

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读