3

我有以下 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手册有一个“数据定义语句”列表,我认为它与上面提到的DDL相同,CREATE TABLE但我只是创建一个临时表。有没有办法解决?

另外,我留下一个空表的事实是否表明查询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);,但这似乎并不影响它。我假设它与交易有关,但我不确定。谁能查明究竟是什么导致了这个错误?

4

1 回答 1

2

您的OPTIMIZE TABLE陈述导致隐式提交。

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

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

所有其他代码只是使工作变得更加复杂,没有任何好处。

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

顺便说一句,缓冲查询与事务无关。它们与一次提取一行的 SELECT 结果集有关,而不是在 PHP 中将整个结果集提取到内存中,然后遍历它。见解释: http: //php.net/manual/en/mysqlinfo.concepts.buffering.php

于 2013-01-29T01:57:51.447 回答