Postgresql - 为什么DROP VIEW命令挂起?

Ste*_*han 11 postgresql view hang sql-drop

我想执行一个简单DROP VIEW ...但它挂起.

SELECT * FROM pg_locks WHERE NOT grantedLock Monitoring上运行了此页面的查询.

但是,他们建议的以下查询不会返回结果:

SELECT bl.pid     AS blocked_pid,
     a.usename  AS blocked_user,
     kl.pid     AS blocking_pid,
     ka.usename AS blocking_user,
     a.query    AS blocked_statement
FROM  pg_catalog.pg_locks         bl
JOIN pg_catalog.pg_stat_activity a  ON a.pid = bl.pid
JOIN pg_catalog.pg_locks         kl ON kl.transactionid = bl.transactionid AND kl.pid != bl.pid
JOIN pg_catalog.pg_stat_activity ka ON ka.pid = kl.pid
WHERE NOT bl.granted;
Run Code Online (Sandbox Code Playgroud)

我现在应该在哪里看?

Ste*_*han 23

最后我弄清楚出了什么问题.以下是查找根本原因的步骤:

第1步:列出未授予的请求锁

select * from pg_locks where not granted;
Run Code Online (Sandbox Code Playgroud)

在我的情况下,尝试使用模式锁定AccessExclusiveLock我想要删除的视图未被授予.这就是我DROP VIEW...挂起的原因.

第2步:找出哪些其他进程存在冲突锁定

select * from pg_locks where relation = <oid_of_view>
Run Code Online (Sandbox Code Playgroud)

在这里,我列出了锁定或试图锁定我的视图的所有进程.我发现了两个进程,一个想要删除视图,另一个进程.

第3步:找出现在正在/正在做的其他进程

select xact_start,query_start,backend_start,state_change,state from pg_stat_activity where pid in (<list_of_other_process(es)_pid>);
Run Code Online (Sandbox Code Playgroud)

在我的情况下,我只有一个进程持有锁.令人惊讶的是,它的状态是:交易闲置

我无法删除视图,因为另一个进程在事务处于空闲状态.我只是杀了它来解决我的问题.例如,如果procpid是8484并假设我的postgresql服务器在Linux机器上运行,那么在shell中,我执行以下命令:

$ kill -9 8484
Run Code Online (Sandbox Code Playgroud)

讨论

如果您遇到类似的问题,可以通过复制步骤1,2,3快速找出正在发生的事情.您可能需要自定义步骤2才能找到其他冲突的进程.

参考

  • 作为参考,这是一个查询中的第 1-3 步:`select * from pg_stat_activity where pid in (select pid from pg_locks where relation = (select relation from pg_locks where not given));` (3认同)

Bor*_*our 9

我有一个类似的问题,但接受的答案对我不起作用,因为我没有管理员权限来终止任何进程。相反,这是我设法解决问题的方式:

  1. 发布SELECT * FROM pg_stat_activity;有关 PostgreSQL 活动的统计信息。
  2. query列中,查找从该视图读取的查询。您可以选择仅查看与您的用户名(username列)相关的行,或者query_start您是否知道问题何时出现,从而缩小搜索范围。可能有不止一行与您不需要的视图相关联。
  3. pid从上述步骤中的所有行中识别出所有行,并将它们一一插入SELECT pg_terminate_backend(<pid>);(而不是<pid>)并发出。

现在你应该可以放弃你的观点了。

请注意,当您使用 终止后端进程时pg_terminate_backend(),您可能会遇到一些错误。原因是终止某些进程可能会自动结束其他进程。因此,某些已识别的 PID 到时可能无效。