现有的答案很有帮助,但缺少故事的内容。
您说要锁定数据库,执行一些查询,然后将其解锁。
如果您这样做是因为在更改仅部分完成时不希望任何其他进程读取数据库,那么您应该知道SQLite具有一项使此操作不必要的功能:transaction。
使用事务,您可以确保在完成更改之前,没有其他进程可以看到您的更改,但是您不必在执行操作时锁定数据库。实际上,当您进行更改时,其他进程仍可以读取您正在处理的数据库的各个部分以及其他进程,该数据库将继续像开始更改之前一样。
如何进行交易?
BEGIN TRANSACTION到数据库。COMMIT到数据库(或者,数据库将接受COMMIT TRANSACTION甚至END TRANSACTION作为同义词)。这种魔术是如何发生的?
当事务打开时,数据库系统会在磁盘上维护您已修改的所有内容的第二个副本。发生这种情况时,可以从数据库中自由读取其他进程。当他们涉及到要修改的数据的一部分时,他们将看到该版本,而没有任何未完成的更改。结束交易后,数据库系统会将更改的版本标记为正式版本,并且不再需要保留其他版本。
各个数据库之间的技术细节有所不同,但是所有支持事务的数据库都将支持等效功能,以确保其他进程不会看到您未完成的更改。
您的其他流程出现错误的问题
即使其他进程在执行事务时仍可以继续读取数据库,但它们仍将无法对其进行写入,并且在事务结束时仍有很小的时间窗,它们将不得不等待读或写。当他们尝试这样做时,他们会注意到数据库已锁定。
这个是正常的。不幸的是,PHP的SQLite3实现(通过PDO和SQLite3类)并没有等待获取锁,只是由于出错而中止了。如果您只希望一次有一个客户端访问数据库,而在Web服务器等共享环境中则不能接受,则此默认行为是可以接受的。
因此,在打开SQLite3连接时,您应该始终设置忙超时。使用PHP 5.3.3时,可以使用SQLite3的busyTimeout()方法来执行此操作,但是如果由于某种原因而无法访问它,则可以使用以下SQL查询来执行:
PRAGMA busy_timeout = 15000
Run Code Online (Sandbox Code Playgroud)
以毫秒为单位,所以是15秒。无论您使用的是PDO还是SQLite3类,它都应独立于您的PHP版本起作用。