1

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

2个并发事务:

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

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

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

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

在这种情况下会发生什么?等待的事务之一最终会超时吗?如果是这样,有没有办法配置超时持续时间?

编辑:死锁超时是我正在寻找的配置吗?

4

2 回答 2

2

是的,您应该deadlock_timeout在 docs 中查找。

但是您的情况并不意味着会出现死锁,'因为 PostgreSQL 正在使用行级锁,并且不清楚您的事务是否针对相同的行并发。

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

ERROR:  could not serialize access due to concurrent update

这是意料之中的,您应该按原样重试交易。

您可以在 wiki 上找到对Serializable 隔离级别的一个很好的概述。

于 2013-02-16T19:50:47.320 回答
1

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 秒后,这是默认超时。另一个答案有更多关于此的信息。

于 2013-02-16T19:44:26.567 回答