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

时间:2013-12-04 11:00:52

标签: postgresql view hang sql-drop

我想执行一个简单的DROP VIEW ...,但它会挂起。

我已在Lock Monitoring上的此页面中运行此查询SELECT * FROM pg_locks WHERE NOT granted

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

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;

我现在应该在哪里看看?

2 个答案:

答案 0 :(得分:21)

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

解决方案

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

select * from pg_locks where not granted;

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

步骤2:查找哪些其他进程存在冲突锁

select * from pg_locks where relation = <oid_of_view>

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

步骤3:找出现在正在/正在进行的其他过程

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

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

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

$ kill -9 8484

讨论

如果您遇到类似问题,可以通过复制步骤1,2,3快速了解发生了什么。您可能需要自定义第2步才能找到其他冲突的进程。

参考

答案 1 :(得分:1)

我遇到了类似的问题,但是我没有管理员权限来杀死任何进程,因此可接受的答案对我不起作用。相反,这是我设法解决问题的方法:

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

现在您应该可以放弃视图了。

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