SQLite数据库永久锁定(直到删除)PHP

时间:2011-08-01 01:42:43

标签: php sqlite locking recess

我们正在使用Recess framework来提供网络服务。作为其中的一部分,我们使用Recess'缓存机制,作为SQLite数据库提供。

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

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

为什么会这样?是否还有其他原因可以让我们开始锁定?锁定为什么会持续存在?有没有办法以编程方式清除它?有没有办法首先防止它?

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

  1. 在缓存访问功能周围放置一个try-catch。如果我们获得异常,只需忽略缓存并通知技术支持人员手动清除缓存。
  2. 对SQLite文件使用互斥锁(使用PHP flock)来防止并发问题(但同样,我甚至不确定这是根本原因)。
  3. 非常感谢任何信息或建议!

1 个答案:

答案 0 :(得分:1)

嗯...

  1. 使技术支持处理不存在的问题。
  2. 忽略SQLite自己锁定的事实。 (SQLite3甚至对它进行了优化!)
  3. 让我的极客站在门口,我会使用“解决方案”3号(你没有列出)并简单地在缓存访问功能周围放置一个try-catch。如果出现异常,请进行短暂睡眠,然后再次调用异常函数。

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

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