代码之家  ›  专栏  ›  技术社区  ›  VDVLeon

事务回滚不起作用

  •  4
  • VDVLeon  · 技术社区  · 14 年前

    我在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->查询(<sql>,<values>)不调用任何其他内容,然后$pdo->准备(<sql>)->执行(<values>)(当然还有额外的错误处理)。

    所以我认为或者MySQL的事务系统不工作,或者PDO的实现不工作,或者我看到了一些错误。

    有人知道问题是什么吗?

    5 回复  |  直到 14 年前
        1
  •  13
  •   oneat    14 年前

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

        2
  •  4
  •   Yada    14 年前

    两个可能的问题:

    1. 表是myisam,不支持事务。使用NYNDB。

    2. 检查以确保自动提交已关闭。

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

        3
  •  3
  •   Marc B    14 年前

    我将输入此作为答案,因为注释太小,无法包含以下内容:

    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表上执行了一些操作,也不会引发任何错误。

        4
  •  2
  •   Powerlord    14 年前

    mysql不支持myisam表类型的事务,不幸的是,这是默认的表类型。

    如果需要事务,则应切换到innodb表类型。

        5
  •  0
  •   dallin    5 年前

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

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

    • 修改表或数据库的任何内容,例如 变更表 , CREATE TABLE 等。
    • 修改表权限的任何内容,例如 ALTER USER SET PASSWORD
    • 锁定该表或启动新事务的任何内容
    • 数据加载语句
    • 行政声明,如 ANALYZE TABLE ,请 FLUSH CACHE INDEX
    • 复制控制语句,例如与从系统或主系统有关的任何内容

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

    如果您只对特定的脚本有这个问题,并且您确定您使用的是InnoDB,那么您可能需要查看脚本中的任何SQL语句是否与这些语句匹配。