我正在使用Postgres 9.1。我想知道在同一事务中使用多个SELECT FOR UPDATES是否可能导致竞争条件。
2个并发交易:
事务1:选择表1上的更新 - 成功获取锁
事务2:选择表2上的更新 - 成功获取锁
事务2:选择表1上的更新 - 等待事务1的锁定释放
事务1:选择表2上的更新 - 等待事务2的锁定释放
在这种情况下会发生什么?其中一个等待交易最终会超时吗?如果是,有没有办法配置超时持续时间?
编辑:我正在寻找的配置是deadlock_timeout吗?
答案 0 :(得分:2)
是的,你应该寻找deadlock_timeout
in the docs。
但是你的场景并不意味着将死锁,'因为PostgreSQL使用行级锁,并且不清楚你的事务是否同意同一行。
另一种选择是使用高于default READ COMMITTED
的序列化级别。但在这种情况下,您的应用程序应准备好接收SQLCODE=40001
的异常:
ERROR: could not serialize access due to concurrent update
这是预期的,您应该按原样重新尝试交易。
对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秒后发生,这是默认超时。另一个答案有更多相关信息。