当前位置: 首页 > 知识库问答 >
问题:

单个事务中的多个SELECT FOR UPDATES是否会导致竞争条件(Postgres)?

公羊伟志
2023-03-14

我使用的是Postgres 9.1。我想知道在同一个事务中使用多个SELECT FOR UPDATES是否可能导致竞争情况。

2个并发事务:

事务1:选择表1上的更新--成功获取锁

事务2:选择表2上的更新--成功获取锁

事务2:选择表1上的更新--等待从事务1释放锁

事务 1:选择更新表 2 -- 等待事务 2 中的锁定释放

在这种情况下会发生什么?其中一个等待的事务最终会超时吗?如果是,是否有方法配置超时持续时间?

编辑:deadlock_timeout我正在寻找的配置吗?

共有2个答案

杜楚
2023-03-14

PostgreSQL将在步骤4检测死锁,并使事务失败。以下是我在psql中尝试时发生的情况(仅显示步骤4):

template1=# SELECT * FROM table2 FOR UPDATE;
ERROR:  deadlock detected
DETAIL:  Process 17536 waits for ShareLock on transaction 166946; blocked by process 18880.
Process 18880 waits for ShareLock on transaction 166944; blocked by process 17536.
HINT:  See server log for query details.
template1=# 

这发生在1秒之后,这是默认超时。另一个答案对此有更多信息。

洪涵亮
2023-03-14

是的,您应该在文档中查找deadlock_timeout

但是您的场景并不意味着会有死锁,因为PostgreSQL正在使用行级锁,并且不清楚您的事务是否正在并发相同的行。

另一种选择是使用比默认READ COMMITTED更高的序列化级别。但在这种情况下,您的应用程序应该准备好接收SQLCODE=40001的异常:

ERROR:  could not serialize access due to concurrent update

这是意料之中的事,您只需按原样重试交易即可。

你可以在wiki上找到一个关于可序列化隔离级别的很好的概述。

 类似资料:
  • 我知道java中的关键字“synchronized”是用于多线程的。然而,副本不是多线程的,而是多进程的。我说的对吗?有什么想法吗?

  • 9.1. 竞争条件 在一个线性(就是说只有一个goroutine的)的程序中,程序的执行顺序只由程序的逻辑来决定。例如,我们有一段语句序列,第一个在第二个之前(废话),以此类推。在有两个或更多goroutine的程序中,每一个goroutine内的语句也是按照既定的顺序去执行的,但是一般情况下我们没法去知道分别位于两个goroutine的事件x和y的执行顺序,x是在y之前还是之后还是同时发生是没法

  • 9.6. 竞争条件检测 即使我们小心到不能再小心,但在并发程序中犯错还是太容易了。幸运的是,Go的runtime和工具链为我们装备了一个复杂但好用的动态分析工具,竞争检查器(the race detector)。 只要在go build,go run或者go test命令后面加上-race的flag,就会使编译器创建一个你的应用的“修改”版或者一个附带了能够记录所有运行期对共享变量访问工具的tes

  • 问题内容: 我有几个工作人员,每个工作人员都拥有与PostgreSQL的连接。工人用不同的桌子操纵。 工作人员处理来自系统外部的并行请求。被访问的表之一是用户表。当收到一些信息时,我首先需要确保表中有该用户的记录。如果没有记录,我希望首先创建一个。 我正在使用以下成语: 的代码是: 然后测试是否返回任何行。 的(简化)代码为: 当我的系统处理与 同一 用户有关 的 不同信息的并行流时,我经常会收到

  • 问题内容: 如何停止MySQL中的竞争条件?当前的问题是由一个简单的算法引起的: 从表中选择一行 如果不存在,将其插入 然后会得到重复的行,或者如果您通过唯一/主键阻止它,则会出现错误。 现在,通常我认为事务在这里有所帮助,但是由于该行不存在,所以事务实际上并没有帮助(或者我是否错过了什么?)。 LOCK TABLE听起来有些矫kill过正,尤其是如果该表每秒更新多次。 我唯一想到的其他解决方案是