2009-06-30 31 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