Postgres中的DELETE查询无限期挂起

时间:2017-07-06 14:55:56

标签: database postgresql

目前我正在尝试删除特定数据库表 api_user 中的行。然而,为了看似无限的时间而删除挂起(因为我一直在寻找答案,目前已经运行了1800秒)。有问题的行有外键家属,但所有这些家属都已被删除,已经过验证。

我通过Postico (只是另一个数据库GUI客户端)运行我的所有数据库内省所以当我取消查询时,我收到此错误消息。

ERROR: canceling statement due to user request
CONTEXT: SQL statement "SELECT 1 FROM ONLY "public"."api_event" x WHERE $1::pg_catalog.text OPERATOR(pg_catalog.= ) "user_id"::pg_catalog.text FOR KEY SHARE OF x"

有些索引引用了此表中的行。 api_event 是一个表,该表具有索引和外键。来自api_event的所有相关行都被删除了。

我已经检查了pg_stat_activity,因为任何可能同时运行的查询都无济于事,所以我不知道下一个问题我应该问的是什么。任何方向都会很棒!

正在运行EXPLAIN DELETE FROM api_user WHERE organization_id = '<replaced value>';会将此信息发送给我:

Delete on api_user (cost=54.94..2903.50 rows=1874 width=6) -> Bitmap Heap Scan on api_user (cost=54.94..2903.50 rows=1874 width=6) Recheck Cond: ((organization_id)::text = '<replaced value>'::text) -> Bitmap Index Scan on api_user_organization_id (cost=0.00..54.47 rows=1874 width=0) Index Cond: ((organization_id)::text = '<replaced value>'::text)

锁定监控

  

您是否检查过它是否正在等待锁定? - a_horse_with_no_name

根据请求,我搜索了数据库中的锁。我使用了这个查询:

 select t.relname,
        l.locktype,
        page,
        virtualtransaction,
        pid,
        mode,
        granted 
 from pg_locks l, 
      pg_stat_all_tables t 
 where l.relation=t.relid 
 order by relation asc;

第一次返回,我的DELETE未运行,来自 pg_class pg_index pg_index 的容器3行锁定。

第二次返回,我的DELETE正在运行,包含21行锁。所有这些都是来自先前已删除的行集的重定名,这些行具有外键或具有此行的索引。

决议之路

通过更多问题和researching,出现了一个有趣的消息,即子表上的所有外键都没有索引。在编写查询以查看哪些外键没有索引后,我注意到 api_event 没有其 api_user 外键的索引。现在 api_event 是一张非常棒的表格。

api_event 上创建索引解决了这个问题。

CREATE INDEX CONCURRENTLY user_id_to_events ON api_event(user_id);

2 个答案:

答案 0 :(得分:0)

我不确定(并且无法发表评论),但我认为您在删除后会遇到严重的重新索引或真空。

答案 1 :(得分:0)

创建索引对于慢速删除查询实际上很有用。 当您使用“explain analyze delete from xx”运行DELETE查询,并取消它太慢时,它将显示:

ERROR:  canceling statement due to user request
CONTEXT:  SQL statement "DELETE FROM ONLY "public"."AAAA" WHERE $1 OPERATOR(pg_catalog.=) "BBBB""

运行CREATE INDEX CONCURRENTLY NAME_OF_INDEX ON AAAA(BBBB)

将解决此问题