2014-05-23 54 views
0

在使用LiveServerTestCase和Selenium測試Django/Postgres應用程序時,我看到間歇性死鎖問題。 LiveServerTestCase繼承自TransactionTestCase,因此在每次測試運行後,所有數據庫表都會被截斷。但有時該截斷導致死鎖,因爲其中一個表被未解析的Postgres事務鎖定。我可以看到,因爲此查詢返回一行:Django LiveServerTestCase,Selenium和Postgres間歇性死鎖

select * from pg_stat_activity 
     where datname='test' and current_query='<IDLE> in transaction'; 

因此,我的應用程序中的某些活動必須創建未解決的事務。我已經梳理了測試,以確保他們在退出之前等待任何更新完成並確信不是這樣。

望着Postgres的日誌,我經常看到這兩行,沒有相應的COMMITROLLBACK

SHOW default_transaction_isolation 
BEGIN 

我懷疑這是造成僵局。任何想法可能會發布此SQL或如何禁用它?這是Django 1.5。

+0

你沒有提到任何提到死鎖的東西。您聽明白了一個僵局是什麼(它不只是那東西已經被鎖定) –

+0

如果我開始兩個'psql',並在第一次啓動事務,但不作任何鎖定,並與第二個檢查,第二個顯示第一個是「閒置交易」。所以在我看來,「閒置交易」本身並不是很多。我會看看'pg_locks',並檢查相關的進程ID是否打開了鎖。應該有一個'virtualxid'類型的鎖,它鎖定在事務本身上。其他鎖可能會出現問題。 – Louis

回答

2

這個死鎖的根本原因是Django 1.5的自動提交行爲。默認情況下,Django 1.5以一個打開的事務運行,如果您執行UPDATEINSERT,則該事務僅由COMMIT關閉。 「閱讀」操作(SELECT)導致我上面提到的無與倫比的BEGIN陳述。看起來如果SELECT發生在測試結束TRUNCATE之前,就會發生死鎖。爲了避免死鎖,只有在所有請求都完成後,測試才能退出,即使這些請求不會導致數據庫寫入。如果Ajax調用在更新後異步更新頁面的部分,這可能會非常棘手。

更好的解決方案是使用Django 1.6,其中atomic()是唯一的(非不推薦)事務創建原語。它不會爲讀取操作打開事務,並且不會留下懸掛的語句BEGIN。測試可以遵循在「寫入」請求待處理時不退出的常識方法。