Reputation: 354
so I'm having issues using transactions in PDO. I am doing a quick test:
<?php
include_once "./init.php";
$sql = "insert into tbTest(cValue) values('1');";
$sttmt = $db->prepare($sql);
$sttmt->execute();
$sql = "SET autocommit=0;";
$sttmt = $db->prepare($sql);
$sttmt->execute();
$db->beginTransaction();
$sql = "SET autocommit=0; insert into tbTest(cValue) values('2');";
$sttmt = $db->prepare($sql);
$sttmt->execute();
$db->rollBack();
$db->beginTransaction();
$sql = "SET autocommit=0; insert into tbTest(cValue) values('3');";
$sttmt = $db->prepare($sql);
$sttmt->execute();
$db->rollBack();
?>
My first insert passes without an itch.
The second insert (in the first transaction) does get rollbacked. however, I start another transaction right after, insert again, and rollback again. Normally, I would expect to receive only "1" in my table.
What happens is that 2 gets rolled back, but then after the third insert, I rollback again and I receive the following error message :
Fatal error: Uncaught exception 'PDOException' with message 'There is no active transaction' in /home/.../.../.../testSQL.php:24 Stack trace: #0 /home/.../.../.../testSQL.php(24): PDO->rollBack() #1 {main} thrown in /home/.../.../.../testSQL.php on line 24
now please disregard the line #, I haven't included the html stuff. Line 24 is the 2nd rollBack(). The one after the insert of the value "3".
I absolutely do not understand what's happening. Why does the first transaction works and not the second? My table does NOT contain "3". I don't know if the rollback worked despite the error message or if the autocomit=0 prevented the value "3" to make it to the table... I have no clue.
Somebody has an explanation?
Thank you,
Upvotes: 0
Views: 561
Reputation: 354
as pointed out by Nigel Ren, the problem was the set autocommit. MyISAM tables cannot manage transactions. I had added the set autocommit as part of my tests back when my table was MyISAM and forgot to remove it when I switched to InnoDB.
The version that works:
<?php
//not in a transaction
$sql = "insert into tbTest(cValue) values('1');";
$sttmt = $db->prepare($sql);
$sttmt->execute();
$db->beginTransaction();
$sql = "insert into tbTest(cValue) values('2');";
$sttmt = $db->prepare($sql);
$sttmt->execute();
$db->rollBack();
$db->beginTransaction();
$sql = "insert into tbTest(cValue) values('3');";
$sttmt = $db->prepare($sql);
$sttmt->execute();
$db->commit();
//not in a transaction
$sql = "insert into tbTest(cValue) values('4');";
$sttmt = $db->prepare($sql);
$sttmt->execute();
$db->beginTransaction();
$sql = "insert into tbTest(cValue) values('5');";
$sttmt = $db->prepare($sql);
$sttmt->execute();
$db->rollBack();
//not in a transaction
$sql = "insert into tbTest(cValue) values('6');";
$sttmt = $db->prepare($sql);
$sttmt->execute();
?>
Only values 1, 3, 4, and 6 make it to the table. This is the expected results!
Thanks again to Nigel Ren!
Upvotes: 1