2010-01-12 145 views
4

我有一個sqlite3數據庫可以被幾個線程(3-4)訪問。我知道sqlite3關於併發性的一般限制,如http://www.sqlite.org/faq.html#q6所述,但我相信這不是問題。sqlite3'數據庫被鎖定'不會因重試而消失

所有的線程都從這個數據庫讀取和寫入。每當我寫,我有以下結構:

  try: 
       Cursor.execute(q, params) 
       Connection.commit() 
      except sqlite3.IntegrityError: 
       Notify 
      except sqlite3.OperationalError: 
       print sys.exc_info() 
       print("DATABASE LOCKED; sleeping for 3 seconds and trying again") 
       time.sleep(3) 
       Retry 

在某些運行時,我甚至不會打這個塊,但是當我做,它永遠不會出來的它(保持重試,但我一直如果我正確理解讀寫器鎖的使用情況,一些等待可以幫助爭用,這聽起來像是死鎖,但我沒有在我的代碼中使用任何事務,並且每個SELECT或INSERT都只是一個關閉,但是某些線程在執行操作時會保持相同的連接(其中包括SELECTS和INSERTS以及其他修飾符的混合)

如果可以,我會修改它爲此遮光,還有修復它的方法(除了使用不同的數據庫引擎)。

+0

你可以建立一個非常小的隔離測試用例來證明這個問題嗎?如果我們有可執行代碼並且可以看到整個事情,那會更容易。 – Dustin 2010-01-12 18:59:36

+0

嗨達斯汀,這可能實際上證明很難,因爲即使有更大的代碼庫,我也很難再現它。我主要想知道這是否是一個常見問題,以及sqlite3中是否存在已知的死鎖問題。我會暫時發佈我不那麼優雅的修補程序。 – BME 2010-01-13 14:26:52

回答

0

每當您嘗試寫入數據庫時​​,Sqlite都會鎖定整個數據庫。有沒有可能你的一個主題是不斷寫作的?只有一個線程觸及數據庫鎖或全部購買其中一個?

+0

Hi tamulj, 沒有一個線程在不停地寫入(線程根據事件處理程序寫入,一次只能寫入幾行)。 – BME 2010-01-12 18:26:33

0

這是一個不太優雅的臨時修復:在寫入時使用外部獨佔鎖,而不是依靠內部sqlite鎖定。問題中的上述代碼塊基本上都包含一個系統範圍的鎖,每個線程在寫入之前必須獲取該鎖。由於sqlite3在寫入時會鎖定整個數據庫,我希望這不會增加更多的開銷。

在另一方面,讀取,而不獲取鎖,我認爲威力工作確定與限制較少的讀者鎖定sqlite3的需求出發。

0

我也遭受過這種情況,在一個每天有200個用戶的網站上(這個網站的瀏覽量可能達到1000頁)。重試只是沒有幫助(我終於增加了他們的數量達到100,之間有短暫的睡眠)。我不記得它是哪個版本的SQLite,但我學到了一個教訓:如果你想對SQLite數據庫進行可靠的併發寫入,那麼你最好使用其他數據庫,比如MySQL或PostgreSQL。

即使您使用OperationalError-s解決問題,也會出現問題,因爲最終將併發寫入SQLite文件會導致性能下降。