2010-05-19 42 views
0

output_values_center1(和其他)繼承output_values。我定期截斷表output_values_center1並加載新數據(在一個事務中)。那時用戶可以請求一些數據,並且他收到錯誤信息。爲什麼它發生(選擇查詢請求只有一條記錄),以及如何避免這樣的問題:select和truncate之間的死鎖(postgresql)

2010-05-19 14:43:17 UTC ERROR: deadlock detected 
2010-05-19 14:43:17 UTC DETAIL: Process 25972 waits for AccessShareLock on relation 2495092 of database 16385; blocked by process 26102. 
    Process 26102 waits for AccessExclusiveLock on relation 2494865 of database 16385; blocked by process 25972. 
    Process 25972: SELECT * FROM "output_values" WHERE ("output_values".id = 122312) LIMIT 1 
    Process 26102: TRUNCATE TABLE "output_values_center1" 
+1

你可以從這個錯誤消息中擴展出關係ID嗎?即'選擇2494865 :: regclass'等。 – araqnid 2010-05-19 18:24:53

+0

謝謝你,問題是更有用然後回答,後看關係id我明白哪裏是問題:) – valodzka 2010-05-20 16:36:34

回答

1
0

我想嘗試這個(在僞代碼)用於截斷:

#define NOWAIT_TIMES 100 
#define SLEEPTIME_USECS (1000*100) 
for (i=0; ; i++) { 
    ok = query('start transaction'); 
    if (!ok) raise 'Unable to start transaction!'; 
    queries = array(
    'lock table output_values in access exclusive mode nowait', 
    'truncate output_values_center1', 
    'commit' 
); 
    if (i>NOWAIT_TIMES) { 
    // we will wait this time, as we tried NOWAIT_TIMES and failed 
    queries[0] = 'lock table output_values in access exclusive mode'; 
    } 
    foreach q in queries { 
    ok = query(q); 
    if (!ok) break; 
    } 
    if (!ok) { 
    query('rollback'); 
    usleep(SLEEPTIME_USECS); 
    } else { 
    break; 
    }; 
}; 

這種方式,你將會很安全從死鎖,因爲父表將被獨佔鎖定。用戶將在截斷運行時阻塞幾分之一秒,並在提交後自動恢復。

但要做好準備,這可以在繁忙的服務器上運行幾秒鐘,因爲當表正在使用時,鎖將失敗並被重試。