0

我们将Recess 框架用于 Web 服务。作为其中的一部分,我们使用 Recess 的缓存机制,作为 SQLite 数据库提供。

我们已经愉快地使用这种缓存机制大约一年了。然而,现在有 3 次我们遇到了 SQLite 数据库被“锁定”并导致问题的问题。我们得到的消息是“异常 'PDOException' 和消息 'SQLSTATE[HY000]:一般错误:5 数据库被锁定'在......”。

我进行了搜索,这似乎是一个常见问题,并且有很多关于如何将其可能性降到最低或防止它的讨论(例如,drupal 委员会)。但是,我的问题似乎与此略有不同。我所描述的情况似乎表明它与并发有关 - 当两个 PHP 进程试图同时访问 SQLite 数据库时,其中一个进程会出现锁定错误。在这种情况下,努力将问题最小化是有意义的。但是对于我的应用程序,当问题开始发生时(可能是因为并发性),SQLite 数据库从那时起永久锁定。从此时起,每一个缓存访问请求都会得到一个 PDOException。我们的解决方案是只删除缓存文件,这不是世界末日,但这需要人工干预,而且意味着我们会丢失构建的缓存数据。

为什么会发生这种情况?是否还有其他原因可以让我们一开始就获得锁?为什么锁会持续存在?有没有办法以编程方式清除它?有没有办法从一开始就阻止它?

到目前为止,我正在考虑的两个“解决方案”是:

  1. 在缓存访问函数周围放置一个 try-catch。如果我们得到异常,只需忽略缓存并通知技术支持手动清除缓存。
  2. 对 SQLite 文件使用互斥锁(使用PHP flock)来防止并发问题(但同样,我什至不确定这是根本原因)。

任何信息或建议将不胜感激!

4

1 回答 1

1

出色地...

  1. 使技术支持处理一个不存在的问题。
  2. 忽略 SQLite 自己锁定的事实。(SQLite3 甚至对其进行了优化!)

让我的极客站在门口,我将使用“解决方案”编号 3(您没有列出),并简单地在缓存访问函数周围放置一个 try-catch。如果遇到异常,请短暂睡眠,然后再次调用引发异常的函数。

thisFunction(...) 
{
    ....
    try
    {
      ....
    }
    catch(Exception $e)
    {
      sleep(rand(1,3))
      thisFunction(...);
    }
    ....
}

这样,您实际上会从 sqlite 试图帮助您的错误中获得一些东西。;)

于 2011-12-12T09:35:12.170 回答