Postgres交易似乎没有任何理由采取AccessExclusiveLock

时间:2013-10-11 18:11:27

标签: postgresql transactions locking

经过大量的谷歌搜索,我想我会问这个问题。我有一段代码对postgres(9.2)数据库执行以下操作:

  1. 开始交易
  2. 删除表上的索引(5个索引)
  3. 在表格中插入一百万行
  4. 重新创建索引
  5. 提交交易。
  6. 我对postgres的阅读告诉我,我应该能够做到这一点,并且仍然允许其他用户从表中进行选择(实际上甚至使用现有的索引,因为它们尚未被删除),而此操作正在进行中。 / p>

    我实际发现的是桌面上的所有其他查询(它们是所有选择查询)都被卡住了。在查看pg_locks和pg_stat_activity表后,我发现我的事务已在表上创建了一个AccessExclusiveLock,阻止其他查询运行。一旦此事务完成,所有其他查询都可以正常执行。

    所以,我的问题是 - 为什么创建索引/插入数据会在表上创建独占锁?不应该使用较少侵入性的锁(例如SHARE锁)吗?

    我的基础是我阅读官方文档here - 所以我不会被任何人要求RTFM:)

    谢谢,
    Jalpesh

2 个答案:

答案 0 :(得分:3)

我也想要这个,但你不能这样做。

它不是创建索引,也不是在表上采用AccessExclusive锁的插入,它是正在执行此操作的drop index。

该文档没有提供获取每种类型锁的每种情况的详尽列表 - 它仅提供说明性示例(但也许这个示例应包含在其中)。

我相信代码的很多部分都假设索引不会在表上的AccessShare锁定时消失。因此,删除索引需要与之冲突。

答案 1 :(得分:1)

我想您希望能够在批量插入期间查询您的表,并通过在插入期间不维护索引来加速此批量插入。

我认为您可以使用此程序实现此目的:

begin;    

maxid = select max(id) from table_name;    

create index table_name_id_tmp_idx where id<=maxid;    

drop index table_name_id_idx;    

commit;    

begin;    

do_bulk_insert();    

create index table_name_id_idx on table_name(id);    

drop index table_name_id_tmp_idx;    

commit;    

对于每个索引都不可能,因为您需要此where谓词用于部分索引,该索引将为现有行返回true并为{}返回false。但是串行列,时间戳等可以工作。