2013-02-28 68 views
3

我不太確定在哪裏問,我希望它在這裏。如果數據庫被鎖定,最簡單的方法來重試SQLite查詢?

我搜索是重試一個SQLite查詢,如果數據庫忙最簡單的解決方案。 我在服務器上使用quassel作爲我的IRC客戶端,我想將舊日誌移動到單獨的數據庫以保持它使用的較小日誌。 我寫了這樣做的腳本是:

CREATE TEMP TABLE delfrom (id integer,val integer); 
ATTACH '/home/irc/oldlog.db' as log; 
BEGIN IMMEDIATE; 
REPLACE INTO delfrom (id,val) select 1337,messageid from backlog where time < strftime('%s', 'now','-14 days') ORDER BY messageid DESC LIMIT 1; 
INSERT INTO log.log (messageid,time,bufferid,type,flags,senderid,message) SELECT messageid,time,bufferid,type,flags,senderid,message FROM backlog WHERE messageid < (SELECT val FROM delfrom where id=1337); 
DELETE FROM backlog WHERE messageid < (SELECT val FROM delfrom where id=1337); 
PRAGMA incremental_vacuum; 
COMMIT; 

我運行它使用的sqlite3 quassel-storage.sqlite < movelog.sql

的問題是,因爲quassel運行時,該執行,有時BEGIN IMMEDIATE;因數據庫被鎖定而失敗。

有人建議我一個簡單的方法來改變這種設置,以便查詢僅僅是重試每隔幾秒鐘,直到它的工作原理? 我讀過python SQLite包裝器有內置?是否有一種特殊的方式我必須激活它,更重要的是,我可以使用python附加第二個數據庫嗎? 對於sqlite3.connect有一個超時參數,但我不太確定這是如何工作的。 Python是否鎖定整個數據庫以便在每個連接上寫入?

我從來沒有注意到使用Python。我更喜歡的解決方案是,sqlite3返回0,當這個錯誤發生,然後把它包裝在一個循環中的shell,但似乎不工作。

回答

4

Python會定期重試。如果數據庫被鎖定,它將不會重試。表鎖只能通過線程,共享連接或其他方法在同一進程內傳播。

數據庫鎖導致當多個進程寫入文件,(簡言之)只要存在雜誌存在。

爲了避免這種情況,WAL模式可用於軸頸。 (編譯journal_mode =沃爾瑪;)

要旋轉數據庫的鎖,你需要像這樣的東西來包裝執行功能:

for x in range(0, timeout): 
    try: 
    with connection: 
     connection.execute(sql) 
    except: 
    time.sleep(1) 
    pass 
    finally: 
    break 
else: 
    with connection: 
     connection.execute(sql) 

最後連接塊將使其正常返回異常。這應該通過檢查數據庫鎖定的例外情況來改進,否則會引發原始異常,但這只是讀者的練習。

6

如果您已將足夠的超時設置爲足夠高,SQLite庫本身將定期重試。

在默認Python包裝,這是sqlite3.connect第二個參數。如果被鎖定

+0

應該在使用sqlite3可執行文件時重試也能工作嗎?因爲它看起來不是! – Josef 2013-03-01 01:09:31

+1

'sqlite3'可執行文件不使用Python。但可以在那裏執行[PRAGMA busy_timeout](http://www.sqlite.org/pragma.html#pragma_busy_timeout)。 – 2013-03-01 10:14:37

+0

謝謝,現在有效,更新我的sqlite3可執行文件後 – Josef 2013-03-04 00:26:54

7

使用WAL模式SQLite的,如果你的版本是大於3.7 https://www.sqlite.org/wal.html

connect = sqlite3.connect(DB, **kwargs) 
connect.execute("PRAGMA journal_mode=WAL") 

據文件「WAL提供了作爲讀者不會阻止作家更多的併發,一個作家不會阻止讀者在閱讀和寫作可以同時進行。「

+0

應該注意[WAL不能在網絡文件系統上運行。所有使用數據庫的進程必須位於同一臺主機上](https://www.sqlite.org/wal.html)。 – davidlatwe 2018-02-21 07:30:10