2013-07-11 79 views
4

我試圖在單個事務中將數百萬行數據加載到一個表(一個「跟隨」表,其中包含用戶表的兩個外鍵以及這些鍵上的關聯索引)。我最初的嘗試導致我的腳本崩潰,因爲系統內存耗盡。爲什麼ALTER TABLE DROP CONSTRAINT在空的桌子上需要很長時間?

一些研究得出的結論是,崩潰是由於外鍵約束,所以我證實表是空的(即導致進程被終止的事務沒有完成)並修改了我的腳本刪除外鍵約束和索引以插入數據。我的意圖是在之後重新創建約束和索引。

但是,ALTER TABLE DROP CONSTRAINT命令刪除表上的第一個外鍵約束需要很長時間(幾十分鐘),儘管表是完全空的。

我能想到的唯一的事情就是它與我寫入表中的大量數據相關,然後沒有提交,因爲腳本崩潰了。但是,當然,由於事務沒有提交,所以我無法在數據庫中找到任何數據的跟蹤。

什麼可能會導致此查詢變慢(或可能根本不能運行;在撰寫本文時,它仍在繼續),我該如何避免它?

在數據庫中還有其他事務處於打開狀態(幾個小時的事務處理會遷移其他非常大的表),但這些事務都沒有觸及下表。

編輯:PG鎖是如下:

db=#  select relation::regclass, * from pg_locks where not granted; 
-[ RECORD 1 ]------+-------------------- 
relation           | auth_user 
locktype           | relation 
database           | 53664 
relation           | 54195 
page               |  
tuple              |  
virtualxid         |  
transactionid      |  
classid            |  
objid              |  
objsubid           |  
virtualtransaction | 5/343 
pid                | 17300 
mode               | AccessExclusiveLock 
granted            | f 

上述(17300)將PID僅僅是ALTER TABLE查詢本身。沒有其他鎖並且沒有進程在等待鎖。

+0

檢查'pg_locks'和*驗證*沒有其他交易n在桌上有一個鎖。即使讀鎖也會阻止「ALTER TABLE」。 –

+0

@CraigRinger編輯添加鎖表info:唯一的鎖是由ALTER TABLE本身創建的鎖。 –

回答

10

檢查pg_locks並驗證沒有其他事務在表上有鎖定。即使讀鎖也會阻止ALTER TABLE

\x 

select 
    pg_class.relname, 
    pg_locks.* 
from pg_locks 
left outer join pg_class ON (pg_locks.relation = pg_class.oid) 
where pg_locks.relation = 'auth_user'::regclass; 

通過在原始查詢過濾爲where not granted你只顯示未決的鎖,沒有鎖that're阻止他們。

事實上,這個鎖沒有被授予告訴我,這是一個鎖定問題。另一個交易在該表上鎖定,以防止ALTER TABLE獲取它需要繼續執行的AccessExclusiveLock。這可能只是一個SELECT在某個時間點從表中編輯的交易。

您可以通過連接在pg_stat_activity找到它:

select 
    c.relname, 
    l.*, 
    psa.* 
from pg_locks l 
inner join pg_stat_activity psa ON (psa.pid = l.pid) 
left outer join pg_class c ON (l.relation = c.oid) 
where l.relation = 'test'::regclass; 

,它會顯示你的交易(或多個)持有或在此表等待鎖,什麼鎖是什麼,聲明目前正在運行這些交易等

(對於那些在舊版本:。pg_stat_activity.pid曾經是procpid因此,如果你使用的是舊的PostgreSQL或更新相應地更改查詢。)

+0

事實證明,由於某種原因,鎖定用戶表(後面的表具有外鍵關係)的單獨進程阻塞了ALTER TABLE查詢。我不明白爲什麼鎖定用戶表會阻止,但這個謎已經解決了。謝謝! –

+0

@JohnBarça試圖編輯:「在9.2之前的Postgres版本中,pg_stat_activity pid被稱爲procpid」。 –

相關問題