MySql事务的一部分正在执行,没有“提交”


Part of a MySql transaction being executed without "commit"

我有一个PHP脚本,从一个数据库中删除旧数据,从另一个数据库中读取数据,然后在第一个数据库中插入新数据。出于显而易见的原因,我希望使用事务来实现这一点,并对每个可能的错误进行回滚。这似乎是有效的,除了一点意想不到的和-对我来说-无法解释的行为。

当(有目的地)中断脚本时,我的所有DELETE语句都被成功回滚,除了一个似乎已经执行的语句。

代码有一个"任务"数组,每个任务都包含一个表名,一个人类可读的数据类型描述,以及源数据库的特定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;
}

有没有人知道,当我中途中断这个脚本时,前两个表被完美回滚,而第三个表无论如何都要执行,这可能是一个合理的解释?

不是所有的MySQL存储引擎都支持事务。如果事务在MyISAM表上操作,那么无论事务的其余部分是提交还是回滚,都将提交该表中的更改。