2009-06-30 86 views
21

我通过phpPgAdmin接口在大型PostgreSQL表上运行了更新语句。当它运行时间太长时,这会超时。如何释放可能的Postgres行锁?

我现在可以从该表中更新一些行,但不是全部。试图更新一些行将挂起。

行被锁定?我怎样才能让这些行更新?

回答

20

你运行的是哪个版本的PostgreSQL?以下假设8.1.8或更高版本(它也可能适用于早期版本,我不知道)。

我认为你的意思是phpPgAdmin超时 - 只要完成查询/更新,PostgreSQL后端就会花费时间。在这种情况下,原始会话可能仍然存在,并且UPDATE查询仍在运行。我建议运行下面的查询托管的PostgreSQL服务器进程的机器上(从chapter 24 of the PostgreSQL docs采取的),看看会话是否还活着:

ps auxwww|grep ^postgres 

几个行应显示:1为postmaster主进程,并“作家”,“统计缓冲区”和“统计收集器”进程各1个。任何剩余的行都用于处理数据库连接的进程。这些行将包含用户名和数据库名称。

希望从中可以看出您执行原始UPDATE的会话是否仍然处于闲置状态。尽管从理论上讲,您可以从系统视图pg_stat_activity中找到更详细的信息,但默认情况下,PostgreSQL未设置为填充最有用的字段(如current_queryquery_start)。有关如何在将来启用此功能,请参阅第24章。

如果您看到会话仍在,请将其取消。您将需要以运行该进程的用户(通常为postgres)或root身份登录 - 如果您没有自己运行服务器,请让您的DBA为您执行此操作。

还有一件事:为了更新表中的行,PostgreSQL避免使用锁。相反,它允许每个写入事务创建一个DB的新“版本”,当事务提交时它将成为“当前版本”,前提是它不会与其他事务同时发生的更新冲突。所以我怀疑你看到的“悬挂”是由其他东西引起的 - 尽管如此,我不确定。 (你是否检查过显而易见的东西,比如包含数据库的磁盘分区是否已满?)

+0

非常好,这工作,谢谢。请注意,当我杀死导致问题的进程时,允许一些其他正在等待锁释放的进程运行。这导致了一些更多的问题。在杀死第一个问题进程之前,我运行ps auxwww | grep^postgres时应该杀死标记为“WAITING”的进程。 – Liam 2009-06-30 11:57:20

+0

很高兴能帮到你:) – 2009-06-30 12:01:31

0

我从来没有使用PostreSQL,但如果它与其他人类似,我会说你必须杀死连接/结束持有锁的事务。

46

可以看到锁。

这里是让比直接使用pg_locks对稍微轻松一点儿一个观点:

CREATE OR REPLACE VIEW public.active_locks AS 
SELECT t.schemaname, 
    t.relname, 
    l.locktype, 
    l.page, 
    l.virtualtransaction, 
    l.pid, 
    l.mode, 
    l.granted 
    FROM pg_locks l 
    JOIN pg_stat_all_tables t ON l.relation = t.relid 
    WHERE t.schemaname <> 'pg_toast'::name AND t.schemaname <> 'pg_catalog'::name 
    ORDER BY t.schemaname, t.relname; 

然后你只需从视图中选择:

SELECT * FROM active_locks; 

而且具有杀死它:

SELECT pg_cancel_backend('%pid%'); 

其他解决方案: http://wiki.postgresql.org/wiki/Lock_Monitoring