PDO:交易不回滚?

时间:2010-03-11 15:41:57

标签: php mysql transactions pdo rollback

我正在通过this tutorial关于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();
}

它运行得很好,就像我想的那样,除非我在某个地方输入错误。就像我在第四个插入语句中创建了一个错误一样,我会在我的数据库中找到三个动物。但我认为应该回滚的东西,这意味着我会在运行此脚本之前找到数据库。

我误解了什么吗?我错过了什么?事务和回滚函数是否做了我认为他们应该做的事情? drop和create语句是否以某种方式“破坏”了事务?这是怎么回事?


更新: 如果我移动$db->beginTransaction();行,那么只有在创建表后事务才开始,我得到的行为是我期待着。因此,如果第三个insert语句失败了,那么在回滚事务之后我会有一个空表(因为它刚刚被重新创建)。仍然想知道为什么当drop和create语句在事务中时它不起作用...

2 个答案:

答案 0 :(得分:19)

查看PHP参考手册:PDO::beginTransaction

  

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

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

答案 1 :(得分:2)

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