【问题标题】:Avoiding sqlite3 database locked避免 sqlite3 数据库锁定
【发布时间】:2011-05-05 08:22:57
【问题描述】:

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

我遇到了似乎很普遍的数据库锁定错误。 我想知道在我的情况下如何避免它。

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

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

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

需要注意的 3 个字段是 reader、status 和 del。

每次线程从资源中读取时,Readers 都会增加,但前提是 status > 0 且 del = 0。

所以我有一些 SQL

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

之后,我检查更新的行数。它应该只有 1。 之后,我尝试通过选择读回该行。即使失败了我也会这样做 更新,因为我需要知道失败的原因。

我尝试将更新和选择都包含在事务中,但这没有帮助。 我已经检查过我是否也在对我的陈述进行敲定。

现在,我认为 sqlite 默认会序列化。我尝试了几种打开模式,但仍然出现相同的错误。

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

有人可以提供一些关于如何避免此类问题的指示吗?我应该将读者锁移出数据库吗?如果我这样做,我应该用什么机制替换它?我在 C++ 下使用 Linux,并且提供了 boost 库。

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

【问题讨论】:

  • 提交更频繁允许对数据库文件进行更细粒度的独占锁,这将减少读者等待表解锁的时间。这是以增加日志文件开销为代价的。查看sqlite.org/lockingv3.html#writing 了解更多信息。

标签: c++ linux sqlite


【解决方案1】:

当你打开数据库时,你应该配置'忙超时'

int sqlite3_busy_timeout(sqlite3*, int ms);

http://www.sqlite.org/c3ref/busy_timeout.html

【讨论】:

  • 嗨,是的,我试过了。它有点帮助。但即使将其设置为 1 秒,它仍然会遇到锁定问题。我启用了 shared_cache 模式,这似乎比忙超时更有帮助。我要两个都试试。
  • 原来 sqlite 对我的应用程序来说太难了。因此,我将 reader 字段移到了内存中。这提高了大约 10000% 的性能,而且我对硬盘的访问更少了。
【解决方案2】:

第一个问题:您是否尝试对所有八个线程使用一个连接?如果是这样,请确保每个线程都有自己的连接。我不知道有什么数据库喜欢这样。

另请查看常见问题解答:http://www.sqlite.org/faq.html

显然 SQLite 必须在 SQLITE_THREADSAFE 预处理器选项设置为 1 的情况下进行编译。他们确实有一种方法来确定这是否是您的问题。

另一个问题是只能从一个进程安全地进行写入。

【讨论】:

  • 是的,每个线程一个连接。我将检查线程安全预处理器选项。我的印象是这是默认设置。
猜你喜欢
  • 1970-01-01
  • 2018-05-25
  • 2015-01-07
  • 1970-01-01
  • 2015-11-22
  • 1970-01-01
  • 2015-08-03
相关资源
最近更新 更多