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

时间:2013-02-16 19:24:18

标签: postgresql

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

2个并发交易:

  

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

     

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

     

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

     

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

在这种情况下会发生什么?其中一个等待交易最终会超时吗?如果是,有没有办法配置超时持续时间?

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

2 个答案:

答案 0 :(得分:2)

是的,你应该寻找deadlock_timeout in the docs

但是你的场景并不意味着死锁,'因为PostgreSQL使用行级锁,并且不清楚你的事务是否同意同一行。

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

ERROR:  could not serialize access due to concurrent update

这是预期的,您应该按原样重新尝试交易。

可以find on the wiki

对Serializable隔离级别进行非常好的概述

答案 1 :(得分: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秒后发生,这是默认超时。另一个答案有更多相关信息。