2013-02-28 71 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