MySQL ROLLBACK doesn't actually rollback
I have the following PHP code:
$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();
Transactions work fine for regular updates / inserts, but the above code is not for some reason. When the above error occurs, I am left with a completely empty table reservations
. I read on the PDO :: beginTransaction page that "some databases, including MySQL, automatically issue an implicit COMMIT when a database definition language (DDL) statement such as DROP TABLE or CREATE TABLE is issued as part of a transaction." The MySQL manual has a list of "Data Definition Statements" which I would assume is the same as mentioned above in the DDL that lists CREATE TABLE
, but I am creating a temporary table. Is there a way to get around this?
Also, does the fact that I was left with an empty table reservations
indicate that there was a commit after the request DELETE QUICK FROM reservations
?
Edit . One more note: the line INSERT INTO reservations
also throws the following error:
The requests cannot be completed while other unbuffered requests are active. Consider using PDOStatement :: fetchAll (). Also, if your code will only work with mysql, you can enable query buffering by setting the PDO :: MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
I've tried doing it $dbh->setAttribute( PDO::MYSQL_ATTR_USE_BUFFERED_QUERY , true);
, but it doesn't seem to affect it. I am guessing it will be transaction related, but I'm not sure. Anyone can determine what exactly is causing this error?
source to share
Your operator OPTIMIZE TABLE
triggers an implicit commit.
I'm not sure what you are trying to do, but it looks like you can shorten your code to:
$dbh->exec("OPTIMIZE TABLE `reservations`");
All other code just makes things harder as there is no amplification.
I also assume that you are using InnoDB tables because MyISAM tables will not support transactions anyway. Every DDL or DML operation on a MyISAM table is implicitly committed immediately.
By the way, buffered queries have nothing to do with transactions. They involve fetching SELECT results one row at a time, compared to putting the entire result set into memory in PHP and then iterating through it. See explanation at: http://php.net/manual/en/mysqlinfo.concepts.buffering.php
source to share