【发布时间】:2017-04-29 20:05:29
【问题描述】:
我并行使用 SQLite 数据库。主要用于阅读——这意味着一切都很好。但也用于写入和删除表格。然后突然我在随机时间得到这个(这表明竞争条件 - 预计会并行运行):
Error: near line 1: database is locked
现在我知道在 10 毫秒内数据库不会被锁定,所以我想等待 10 毫秒再试一次,但我找不到捕获该错误的方法。
我怎样才能发现这个错误?
【问题讨论】:
-
如果在你使用的 SQLite 包装器中有办法做到这一点,你可能应该设置一个“忙超时”(参见SQLite docs),SQLite 应该处理这个问题。建议值似乎在 5-10s 左右(即 5000-10000 的值)。
-
问题似乎是它没有被视为 BUSY,而是被视为 LOCKED,并且它假设(错误地)锁定不能消失。
-
可以在此处阅读:sqlite.org/cvstrac/wiki?p=DatabaseIsLocked SQLITE_LOCKED 错误与 SQLITE_BUSY (5) 不同。 SQLITE_BUSY 表示另一个数据库连接(可能在另一个进程中)正在以阻止您使用它的方式使用数据库。 SQLITE_LOCKED 表示争用源是内部的,并且来自收到 SQLITE_LOCKED 错误的同一数据库连接。所以等待和重试可能无济于事。
-
我不知道这是否是您遇到的问题,但我想我会按照您提到的“并行”将其扔掉。我最近遇到了这个问题,发现问题是我在
fork()下同时使用了两个单独的数据库句柄。当我重构代码以传递单个句柄并取消第二个句柄时,问题就消失了。这记录在docs -
@GeorgMavridis:这很重要;谢谢。我假设一个 locked 错误就像一个文件系统锁,它可以被任何进程独立应用。听起来 OP 的问题是所有子进程都使用相同的数据库连接,因此彼此锁定。