如果你正在使用 PDO::SQLITE 並且需要支援高併發的鎖定,請嘗試在呼叫 beginTransaction() 之前準備你的語句,而且你可能也需要在 SELECT 語句上呼叫 closeCursor(),以防止驅動程式認為有開啟的交易。
這是一個範例(Windows,PHP 版本 5.2.8)。我們透過開啟兩個瀏覽器分頁到這個腳本並同時執行它們來測試。如果我們在 prepare 之前放置 beginTransaction,第二個瀏覽器分頁將會命中 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;
}
}
}
?>