MySQL ROLLBACK实际上没有回滚

时间:2013-01-29 01:07:46

标签: php mysql pdo

我有以下PHP代码:

$dbh->beginTransaction();
$dbh->exec("LOCK TABLES
    `reservations` WRITE, `settings` WRITE");
$dbh->exec("CREATE TEMPORARY TABLE
        temp_reservations
    SELECT * FROM reservations");
$dbh->exec("ALTER TABLE
        `temp_reservations`
    ADD INDEX ( conf_num ) ; ");

// [...Other stuff here with temp_reservations...]

$dbh->exec("DELETE QUICK FROM `reservations`");
$dbh->exec("OPTIMIZE TABLE `reservations`");
$dbh->exec("INSERT INTO `reservations` SELECT * FROM temp_reservations");

var_dump(GlobalContainer::$dbh->inTransaction()); // true
$dbh->exec("UNLOCK TABLES");
$dbh->rollBack();

交易对于定期更新/插入工作正常,但上述代码由于某种原因不适用。当上面发生错误时,我会留下一个完全空的reservations表。我在PDO::beginTransaction页面上读到“某些数据库(包括MySQL)在事务中发出数据库定义语言(DDL)语句(如DROP TABLE或CREATE TABLE)时自动发出隐式COMMIT ”。 MySQL manual有一个“数据定义语句”列表,我假设它与上面提到的列出CREATE TABLE的DDL相同,但我只是创建一个临时表。有没有办法解决这个问题?

另外,我留下一个空reservations表的事实是否显示提交 DELETE QUICK FROM reservations查询后发生了

修改:另外请注意,INSERT INTO reservations行也会产生以下错误:

  

当其他未缓冲的查询处于活动状态时,无法执行查询。考虑使用PDOStatement :: fetchAll()。或者,如果您的代码只是针对mysql运行,则可以通过设置PDO :: MYSQL_ATTR_USE_BUFFERED_QUERY属性来启用查询缓冲。

我尝试过$dbh->setAttribute( PDO::MYSQL_ATTR_USE_BUFFERED_QUERY , true);,但这似乎并没有影响它。我假设它与交易有关,但我不确定。任何人都可以确定导致此错误的确切原因吗?

1 个答案:

答案 0 :(得分:2)

您的OPTIMIZE TABLE语句导致隐式提交。

我不确定您要做什么,但看起来您可以将代码缩短为:

$dbh->exec("OPTIMIZE TABLE `reservations`");

所有其他代码只是让工作更复杂,没有收获。

我还假设您正在使用InnoDB表,因为MyISAM表无论如何都不支持事务。 MyISAM表上的每个DDL或DML操作都会立即隐式提交。

顺便说一下,缓冲查询与事务无关。它们与每次获取一行SELECT结果集有关,而不是在PHP中将整个结果集提取到内存中,然后迭代它。请参阅:http://php.net/manual/en/mysqlinfo.concepts.buffering.php

中的说明