php的SQLite3Stmt类会导致锁定问题吗?


Does PHP's SQLite3Stmt class cause locking problems?

我正在运行PHP 5.3.3 (CentOS 6.5的最新版本)作为Prefork的Apache模块。

我发现,如果脚本以某种方式耗尽时间或内存,那么SQLite3数据库将永远锁定,直到Apache重新启动。

可再生的测试:

// Open a connection to the database.
$db = new SQLite3('/path/to/test.db');
// Get a reserved lock.
$db->exec('BEGIN IMMEDIATE TRANSACTION');
// Construct a prepared statement SQLite3Stmt object.
$st = $db->prepare('SELECT value FROM sometable WHERE key=:key');
// Emulate the script running off the rails while calling the prepared statement.
while(true)
{
    $st->bindValue(':key', 1);
}

如果你运行这个脚本,它当然会耗尽执行时间和/或内存。但是,从那时起,数据库被原始Apache进程锁定。在Apache重新启动之前,没有脚本可以在数据库上创建另一个保留锁。

当脚本终止时,PHP不应该关闭数据库连接吗?这是PHP中的一个bug吗?它会通过将其作为FastCGI进程运行来解决吗?

在内部,SQLite对数据库文件使用POSIX建议锁。

操作系统将在进程退出时清除此锁。但是,只要有活动事务的Apache进程还在运行,这个锁就会一直存在。

如果您有行为不正常的脚本,您应该以终止它们的方式运行它们,从而杀死整个进程。