【问题标题】:Part of a MySql transaction being executed without "commit"MySql 事务的一部分在没有“提交”的情况下执行
【发布时间】:2011-12-29 11:05:15
【问题描述】:

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

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

代码有一个“任务”数组,每个数组都包含表名、对数据类型的可读描述以及源数据库的特定 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 的表?
  • 说实话,这种东西更适合存储过程(尤其是sa系列的原子删除)......
  • 我会选择 Darhazer。在 mysql 客户端中尝试 SHOW TABLE STATUS 并查找任何非 InnoDB 表并检查它们是否是事务性的。
  • 宾果游戏。这是一个 MyISAM 表。为什么?我一点头绪都没有。我想我现在要去让一个数据库设计师被画出来,分成四等份并斩首。如果您可以将您的答案作为“答案”,那么我可以接受它作为正确的答案,Darhazer。非常感谢。要是我一周前来这里就好了。

标签: php mysql transactions pdo


【解决方案1】:

并非 MySQL 中的所有存储引擎都支持事务。如果事务在 MyISAM 表上运行,则无论事务的其余部分是否已提交或回滚,都将提交该表中的更改。

【讨论】:

    猜你喜欢
    • 2012-04-22
    • 2015-09-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多