PDO:事务不会回滚吗?

8

我正在学习PDO相关的内容,现在遇到了关于事务的部分。省略连接代码,以下是PHP代码:

try
{
    $db->beginTransaction();

    $db->exec('DROP TABLE IF EXISTS animals');

    $db->exec('CREATE TABLE animals ('
        .'animal_id MEDIUMINT(8) NOT NULL AUTO_INCREMENT PRIMARY KEY,'
        .'animal_type VARCHAR(25) NOT NULL,'
        .'animal_name VARCHAR(25) NOT NULL)'
        .'ENGINE=INNODB');

    $db->exec('INSERT INTO animals (animal_type, animal_name) VALUES ("emu", "bruce")');
    $db->exec('INSERT INTO animals (animal_type, animal_name) VALUES ("funnel web", "bruce")');
    $db->exec('INSERT INTO animals (animal_type, animal_name) VALUES ("lizard", "bruce")');
    $db->exec('INSERT INTO animals (animal_type, animal_name) VALUES ("dingo", "bruce")');
    $db->exec('INSERT INTO animals (animal_type, animal_name) VALUES ("kangaroo", "bruce")');
    $db->exec('INSERT INTO animals (animal_type, animal_name) VALUES ("wallaby", "bruce")');
    $db->exec('INSERT INTO animals (animal_type, animal_name) VALUES ("wombat", "bruce")');
    $db->exec('INSERT INTO animals (animal_type, animal_name) VALUES ("koala", "bruce")');
    $db->exec('INSERT INTO animals (animal_type, animal_name) VALUES ("kiwi", "bruce")');

    $db->commit();

    echo 'Table re-created and data entered successfully.';
}
catch(PDOException $e)
{
    $db->rollback();

    echo $e->getMessage();
}

它运行得很好,就像我想的那样,除非我在某个地方犯了一个错误。比如说,如果我在第四个插入语句中创建了一个错误,我会在我的数据库中找到三个动物。但是我认为事情应该被回滚,这意味着我会发现数据库像运行此脚本之前一样。
我有什么误解吗?我错过了什么?事务和回滚函数是否做了与我想象中不同的事情?删除和创建语句是否在某种程度上“破坏”了事务?这里发生了什么?
更新:如果我将`$db->beginTransaction();`移动到表格创建后才开始事务,我会得到我期望的行为。所以如果第三个插入语句失败,事务回滚后我会得到一个空表(因为它刚刚被重新创建)。但我仍然想知道为什么当删除和创建语句在事务中时它不起作用...
2个回答

19

请参考PHP参考手册:PDO::beginTransaction

一些数据库,包括MySQL,在事务内执行数据定义语言(DDL)语句,例如DROP TABLE或CREATE TABLE时,会自动发出隐式COMMIT。这个隐式的COMMIT会阻止您回滚事务边界内的任何其他更改。

这就解释了为什么会发生这种情况,这是MySQL的限制,而不是PDO / PHP的限制。


2
确保所有表都支持事务。例如,MyISAM不支持事务。

2
这更像是一条评论而不是答案。 - hakre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接