简体   繁体   中英

MySQL: PDO transactions not working properly

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,

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM