我有一个PHP脚本,它从数据库中删除旧数据,从另一个数据中读取数据,然后在第一个数据中插入新数据。出于显而易见的原因,我想使用事务,并对每个可能的错误进行回滚。这似乎有效,除了一点意外和 - 对我来说 - 无法解释的行为。
当(故意)中断脚本时,我的所有DELETE语句都会成功回滚,除了一个似乎已经执行过的语句。
代码有一个'tasks'数组,每个都有一个数组,其中包括一个表名,一个人类可读的数据类型描述,以及源数据库的特定SELECT语句。这是'worklist'数组的一个片段:
$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;
}
有没有人知道当我中途打断这个脚本时前两个表完全回滚可能是一个合理的解释,而第三个表无论如何都要执行?
答案 0 :(得分:2)
并非MySQL中的所有存储引擎都支持事务。如果事务在MyISAM表上运行,则无论事务的其余部分是提交还是回滚,都将提交该表中的更改。