Postgres 中的 DELETE 查询无限期挂起

Dar*_*iet 7 database postgresql

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

\n\n

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

\n\n
ERROR: canceling statement due to user request\nCONTEXT: 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"\n
Run Code Online (Sandbox Code Playgroud)\n\n

有一些索引引用了该表中的行。api_event是一张表,该表具有索引和外键。api_event 中的所有相关行均已删除。

\n\n

我已经检查了 pg_stat_activity 是否有任何可能同时运行但无济于事的查询,因此我不确定我应该问的下一个问题是什么。任何方向都会很棒!

\n\n

跑步EXPLAIN DELETE FROM api_user WHERE organization_id = \'<replaced value>\';将这个返回给我:

\n\n

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

\n\n

锁监控

\n\n
\n

你检查过它是否正在等待锁吗?\xe2\x80\x93 a_horse_with_no_name

\n
\n\n

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

\n\n
 select t.relname,\n        l.locktype,\n        page,\n        virtualtransaction,\n        pid,\n        mode,\n        granted \n from pg_locks l, \n      pg_stat_all_tables t \n where l.relation=t.relid \n order by relation asc;\n
Run Code Online (Sandbox Code Playgroud)\n\n

第一次返回时,我的 DELETE 没有运行,容器包含来自pg_classpg_indexpg_namespace的 3 行锁。

\n\n

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

\n\n

解决之路

\n\n

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

\n\n

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

\n\n
CREATE INDEX CONCURRENTLY user_id_to_events ON api_event(user_id);\n
Run Code Online (Sandbox Code Playgroud)\n

小智 0

我不确定(也无法发表评论),但我认为您在删除后正在经历严重的重新索引或真空。