如果您正在使用 PDO::SQLITE 并且需要支持具有锁定的高并发级别,请尝试在调用 beginTransaction() 之前预处理您的语句,并且您可能还需要在 SELECT 语句上调用 closeCursor() 以防止驱动程序认为存在打开的事务。
这是一个示例(Windows,PHP 版本 5.2.8)。我们通过打开此脚本的 2 个浏览器选项卡并同时运行它们来测试此问题。如果我们将 beginTransaction 放在 prepare 之前,则第二个浏览器选项卡将命中 catch 块,并且 commit 将抛出另一个指示事务仍处于打开状态的 PDOException。
<?php
$conn = new PDO('sqlite:C:\path\to\file.sqlite');
$stmt = $conn->prepare('INSERT INTO my_table(my_id, my_value) VALUES(?, ?)');
$waiting = true; while($waiting) {
try {
$conn->beginTransaction();
for($i=0; $i < 10; $i++) {
$stmt->bindValue(1, $i, PDO::PARAM_INT);
$stmt->bindValue(2, 'TEST', PDO::PARAM_STR);
$stmt->execute();
sleep(1);
}
$conn->commit();
$waiting = false;
} catch(PDOException $e) {
if(stripos($e->getMessage(), 'DATABASE IS LOCKED') !== false) {
$conn->commit();
usleep(250000);
} else {
$conn->rollBack();
throw $e;
}
}
}
?>