1
我有一個PHP腳本,它從數據庫中刪除舊數據,從另一個數據中讀取數據,然後在第一個數據中插入新數據。出於顯而易見的原因,我希望通過使用事務來回滾每一個可能的錯誤。這似乎工作,除了一點意外和 - 對我來說 - 無法解釋的行爲。正在執行而沒有「提交」的MySql事務的一部分
當(有目的地)中斷腳本時,我的所有DELETE語句都成功回滾,除了似乎已經執行的語句之外。
代碼包含一個'tasks'數組,每個數組都包含一個表名,一個人類可讀的數據類型描述和源數據庫的特定SELECT語句。下面是「工作列表」數組的一個片段:
$worklist = array(
array(
"table" => "campaign",
"description" => "campaign details",
"selectsql" => "SELECT ... "
),
array(
"table" => "product",
"description" => "product",
"selectsql" => "SELECT ... "
),
...
array(
"table" => "context_search",
"description" => "product details for search",
"selectsql" => "SELECT ... "
)
);
定義這個「工作表」後,我如下開始我的交易:
$dbfront = new PDO(...);
$dbfront->exec("SET AUTOCOMMIT = 0");
$dbfront->beginTransaction();
$dbfront->exec("SET FOREIGN_KEY_CHECKS=0");
之後通過工作列表我循環來刪除舊數據如下:
foreach($worklist as $job){
$deleter = $dbfront->prepare("DELETE FROM "
. $job["table"] .
" WHERE
campaign_id = " . $campaign_id .
";");
try{
$deleter->execute();
echo $deleter->rowCount() . "lines of old data deleted from " . $job["table"] . " table\n";
} catch (exception $e){
echo $e . "\n";
$dbfront->rollBack();
echo "An error occurred. All changes have been rolled back.\n";
exit;
}
}
然後,還有的代碼從其他數據庫中選擇新的數據並將其插入到「dbfront」,然後在最後,我有這樣的一部分,提交更改:
try {
$dbfront->commit();
echo "\nAll changes committed\n";
} catch (Exception $e) {
echo $e . "\n";
$dbfront->rollBack();
echo "An error occurred. All changes have been rolled back.\n";
exit;
}
沒有人有任何想法可能是一個合理的解釋時,我打斷這個腳本半路前兩個表被完全回滾,而第三個被無論什麼執行?
事務的已提交部分是否與不同的表一起工作 - 不是InnoDB可能? – 2011-12-29 11:09:11
說實話,這種東西更適合於存儲過程(尤其是sa系列的原子刪除)... – gbn 2011-12-29 11:11:33
我會和Darhazer一起去的。嘗試在MySQL客戶端中使用SHOW TABLE STATUS並查找任何非InnoDB表並檢查它們是否是事務性的。 – Jaydee 2011-12-29 11:19:25