避免SQLite3数据库被锁定

7

我有一个使用sqlite (3.7.3)的多线程应用程序。

我遇到了数据库锁定错误,这似乎是相当普遍的。我想知道如何在我的情况下避免这种情况。

让我描述一下我正在构建的内容。抱歉,代码太大太复杂了。

我有大约8个线程同时访问数据库。这些线程中的任何一个都可以同时读取或写入。

数据库中表中的每一行都有一个文件路径,指向资源以及与该资源相关的其他属性。

注释中的3个字段为readers,status和del。

只有当status>0且del=0时,每次线程从资源中读取时,读者才会递增。

所以我有一些SQL执行以下操作:

UPDATE resource set readers=readers+1 where id=? AND del=0 AND status>0

之后,我会检查更新的行数。应该只有1行被更新。

即使更新失败,我也会尝试使用select读取该行。因为我需要知道它失败的原因。

我尝试将更新和选择操作都包含在一个事务中,但这并没有帮助。我已经确认了我在语句结束时调用了finalize函数。

现在,我认为sqlite默认是串行化的。我尝试了几种打开模式,但仍然遇到了相同的错误。

在你问之前,我不打算转向mysql。我绝对需要零配置。

有人能提供一些如何避免这种问题的指导吗?我应该将读者锁移出数据库吗?如果我这样做,我应该用什么机制来代替它呢?我正在使用C++下的Linux,并且有boost库可用。

编辑:有趣的是,在我的更新调用后添加COMMIT可以显著改善情况。


1
更频繁地提交操作可以对数据库文件进行更细粒度的排他锁,从而减少读者等待表解锁所花费的时间。但这会增加日志文件的开销。请访问http://sqlite.org/lockingv3.html#writing了解更多信息。 - checker
2个回答

4

3
好的,我来翻译一下。请看下面的内容:嗨,是的,我试过了。它有点帮助。但是,即使设置高达1秒,它仍然会遇到锁定问题。我已启用共享缓存模式,这似乎比繁忙超时更有帮助。我将尝试两者。 - hookenz
结果发现我的应用程序对sqlite的使用太过频繁了。因此,我将读取字段移到内存中。这样可以提高性能约10000%,并且减少了对硬盘的访问次数。 - hookenz

2
第一个问题:您是否尝试使用一个连接来使用八个线程?如果是,请确保每个线程都有自己的连接。我不知道有哪个数据库可以承受这样的方式。
另外请查看常见问题解答:http://www.sqlite.org/faq.html 显然,SQLite必须使用设置为1的SQLITE_THREADSAFE预处理选项进行编译。他们确实有一种方法来确定这是否是您的问题。
另一个问题是只有一个进程可以安全地进行写入操作。

是的,每个线程一个连接。我会检查线程安全的预处理器选项。不过,我之前的印象是这是默认设置。 - hookenz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接