PostgreSQL死锁问题:无显式锁定

3

我使用的是PostgreSQL 9.2,我没有在任何地方使用显式锁定,既没有使用LOCK语句也没有使用SELECT ... FOR UPDATE。然而,最近我遇到了ERROR: 40P01: 死锁检测到。尽管死锁检测到的查询被包装在事务块中,但是为什么会出现这种情况呢?


你能展示一下在哪些查询/模式中发生了死锁吗?你的事务中是否使用了哈希索引? - Chris Farmiloe
2个回答

10

你不需要任何显式的LOCK来进入死锁状态。以下是一个非常简单的演示,仅使用INSERT语句:

create table a(i int primary key);
create table b(i int primary key);

第一次会话执行以下操作:

begin;
insert into a values(1);

然后第二个会话执行:

begin;
insert into b values(1);
insert into a values(1);
-- here it goes into waiting for session #1 to finish its transaction

然后第一次会话执行以下操作:

insert into b values(1);

然后死锁发生:

错误: 检测到死锁
详细信息: 进程9571等待事务4150上的ShareLock;被进程9501阻塞。
进程9501等待事务4149上的ShareLock;被进程9571阻塞。
提示: 请查看服务器日志以获取查询详细信息。

简单的UPDATE或UPDATE和INSERT的组合也可能发生相同的情况。这些操作会获取隐式锁,如果它们在不同会话中以不同顺序进行,它们可能会导致死锁。


2

我首先怀疑哈希索引问题。

  • 将所有hash索引转换为B-tree索引
  • 如果合适,使用Serializable隔离级别。

我没有任何哈希索引,但它们怎么可能是原因呢? - Vadim Samokhin
1
由于实现中使用了哈希桶级别锁来进行读写访问,因此这是可能的。 - Chris Farmiloe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接