5

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

  1. 开始交易
  2. 在表上删除索引(5 个索引)
  3. 在表中插入一百万行
  4. 重新创建索引
  5. 提交事务。

我对 postgres 的阅读告诉我,当此操作正在进行时,我应该能够做到这一点,并且仍然允许其他用户从表中进行选择(实际上甚至使用现有索引,因为它们还没有被删除)。

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

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

我是根据我阅读这里的官方文档来做这个的——所以我不会因为任何人向 RTFM 提出要求而生气 :)

谢谢,
贾尔佩什

4

2 回答 2

4

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

在表上获取 AccessExclusive 锁的不是创建索引,也不是插入,而是删除索引。

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

我相信代码的许多部分都假设在持有表上的 AccessShare 锁时索引不会消失。所以删除索引需要与之冲突。

于 2013-10-11T19:59:24.397 回答
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插入的行。但是串行列、时间戳等可以工作。

于 2013-10-12T19:49:45.273 回答