【问题标题】:Why is my "CREATE INDEX CONCURRENTLY .." command blocked by a "SELECT FROM" query? (Postgres 9.6)为什么我的“CREATE INDEX CONCURRENTLY ..”命令被“SELECT FROM”查询阻止? (Postgres 9.6)
【发布时间】:2020-09-28 03:18:47
【问题描述】:

我正在运行迁移以创建索引,但迁移被另一个查询阻止。在发现有另一个查询阻止了我的迁移后,我解决了这个问题;并且在取消阻塞查询后,我能够成功运行迁移。

(我的服务器在 Linux 上使用 Postgres 9.6)

以下是我发现我的迁移被阻止的方式:

SELECT
    activity.pid,
    activity.usename,
    activity.query,
    blocking.pid AS blocking_id,
    blocking.query AS blocking_query
FROM pg_stat_activity AS activity
JOIN pg_stat_activity AS blocking ON blocking.pid = ANY(pg_blocking_pids(activity.pid));

返回以下结果:

| pid | usename | query                                                                           | blocking_id | blocking_query                                                              |
|-----+---------+---------------------------------------------------------------------------------+-------------+-----------------------------------------------------------------------------|
| 123 | my_user | CREATE  INDEX CONCURRENTLY "idx_orders_on_widget_id" ON "orders"  ("widget_id") | 456         | SELECT  "customers".* FROM "customers" WHERE "customers"."id" = $1 LIMIT $2 |

我的迁移(CREATE INDEX CONCURRENTLY .. 查询)怎么可能被SELECT .. FROM .. 查询阻止?即使运行阻塞查询的进程处于僵尸状态,我也不明白我的索引创建查询如何被“SELECT .. FROM ..”查询阻塞。

谁能提供有关这如何可能的见解?

如果有帮助,这是我的架构(针对这个问题进行了简化):

订单

id

widget_id

customer_id(FK 到 Customers

客户

id

company_id(FK 到 Companies

公司

id

一些补充说明:

  • 我发现索引在我运行迁移大约 8 小时后被阻止。
  • 杀死阻塞查询后,我删除了idx_orders_on_widget_id 索引并重新运行迁移以重新创建索引。
  • 第二次重新运行迁移后,索引创建在大约 10 分钟内完成
  • 服务器在 Linux 上运行 Postgres 9.6

【问题讨论】:

    标签: sql postgresql transactions ddl pg-stat-statements


    【解决方案1】:

    The documentation 说:

    PostgreSQL 支持在不锁定写入的情况下构建索引。通过指定CREATE INDEXCONCURRENTLY 选项来调用此方法。使用此选项时,PostgreSQL 必须对表执行两次扫描,此外,它必须等待所有可能修改或使用索引的现有事务终止

    【讨论】:

    • 感谢您的回答,并参考文档 :) 它解释了处于僵尸状态的 SELECT .. FROM .. 查询如何阻止索引创建。但是SELECT .. FROM .. 查询不是必须修改或使用该索引吗?我在上面找到的阻塞查询是SELECT "customers".* FROM "customers" WHERE "customers"."id" = $1 LIMIT $2,它似乎没有修改或使用orders 表上的新索引widget_id。或者我错过了什么?
    • 它说“可能会修改”。也许同一事务中的下一条语句会尝试访问索引?
    • 啊,这是一个很好的观点,它解释了这种行为。是否也有可能同一事务中的 previous 语句已经尝试访问索引?然后在事务的后期,进程在SELECT .. FROM .. 查询期间进入僵尸状态。如果是这样,这是否意味着交易正在使用索引?
    • PostgreSQL 不检查。它只是等待并发事务完成。
    猜你喜欢
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-23
    • 2020-01-26
    • 2018-04-18
    • 2019-07-25
    • 2021-07-28
    相关资源
    最近更新 更多