事务回滚不起作用

时间:2010-02-17 15:08:40

标签: php mysql pdo transactions

我已经在PDO系统周围创建了一个具有额外功能的数据库包装器(是的,我知道包装器的包装器,但它只是带有一些额外功能的PDO)。但我注意到了一个问题。

下面的内容并不像它应该的那样:

<?php
var_dump($db->beginTransaction());

$db->query('
 INSERT INTO test
 (data) VALUES (?)
 ;',
 array(
  'Foo'
 )
);
print_r($db->query('
 SELECT *
 FROM test
 ;'
)->fetchAll());

var_dump($db->rollBack());

print_r($db->query('
 SELECT *
 FROM test
 ;'
)->fetchAll());
?>

var_dump显示beginTransaction和rollBack函数返回true,因此没有错误。

我预计第一个print_r调用显示N个项目的数组,第二个调用显示N-1个项目。但事实并非如此,它们都显示相同数量的物品。

我的$ db-&gt;查询(&lt; sql&gt;,&lt; values&gt;)之后不再调用$ pdo-&gt; prepare(&lt; sql&gt;) - &gt; execute(&lt; values&gt; )(有额外的错误处理)。

所以我认为或MySQL的交易系统不起作用,或者PDO的实现不起作用或者我看错了。

有人知道问题是什么吗?

5 个答案:

答案 0 :(得分:14)

检查您的数据库类型是否等于innoDB。总之,您必须检查数据库是否支持事务。

答案 1 :(得分:4)

两个可能的问题:

  1. 该表是MyISAM,不支持事务。使用InnoDB。

  2. 检查以确保自动提交为OFF。

  3. http://www.php.net/manual/en/pdo.transactions.php

答案 2 :(得分:3)

我正在输入这个作为答案,因为评论很小以包含以下内容:

PDO只是各种低级数据库接口库的包装器。如果低级库没有抱怨,PDO也会。由于MySQL支持事务,因此任何事务操作都不会返回语法错误等。您可以在事务中使用MyISAM表,但对它们执行的任何操作都将完成,就像自动提交仍处于活动状态一样:

mysql> create table myisamtable (x int) engine=myisam;
Query OK, 0 rows affected (0.00 sec)

mysql> create table innodbtable (x int) engine=innodb;
Query OK, 0 rows affected (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into myisamtable (x) values (1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into innodbtable (x) values (2);
Query OK, 1 row affected (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select * from myisamtable;
+------+
| x    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> select * from innodbtable;
Empty set (0.00 sec)

mysql>

正如您所看到的,即使事务处于活动状态,并且在MyISAM表上执行了某些操作,也不会引发任何错误。

答案 3 :(得分:2)

MySQL不支持MyISAM表类型的事务,遗憾的是它是默认的表类型。

如果您需要交易,则应切换到InnoDB表类型。

答案 4 :(得分:0)

发生这种情况的另一个原因是某些类型的SQL语句会导致立即自动提交。我有一个很大的脚本运行在一个事务中,该事务立即被提交并忽略了该事务。我最终发现这是因为任何ALTER TABLE语句都会立即导致一次提交。

导致自动提交的语句类型为:

  • 任何修改表或数据库的内容,例如ALTER TABLECREATE TABLE等。
  • 任何修改表权限的内容,例如ALTER USERSET PASSWORD
  • 任何可锁定该表或启动新事务的东西
  • 数据加载语句
  • 行政声明,例如ANALYZE TABLEFLUSHCACHE INDEX
  • 复制控制语句,例如与从属或主控有关的任何事情

更多信息和完整列表可以在这里找到:https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html

如果仅在特定脚本中遇到此问题,并且确定使用的是InnoDB,则可能要查看脚本中是否有任何SQL语句与之匹配。