回滚多个查询

时间:2011-12-12 19:08:36

标签: mysql database

如何执行多个查询,usen commit(),如果出现问题,请回滚所有查询?

我注意到如果我将查询包装并在try / catch中提交,则只回滚不成功的查询

try{

  $pdo->beginTransaction();

  // create 10 tables
  foreach($queries as $query)
    $result = $pdo->query($query);

  $pdo->commit();

}catch(PDOException $e){

  // here if one of the tables fail to be created, undo all operations
  $pdo->rollBack();  

}

3 个答案:

答案 0 :(得分:3)

MySQL不支持嵌入式交易。

如果您认为自己正在进行部分回滚,则表明您检错了。特别是,不成功的查询甚至不会运行,因此没有什么可以回滚。会发生什么事情是因为您忘记了START TRANSACTION语句或因为您的表不是InnoDB而没有真正的事务。

编辑:我刚刚看到您更新了问题。您无法回滚CREATE TABLE等DDL语句。您只能回滚DML语句(SELECTINSERTUPDATE ...)。这不是MySQL限制,它是我所知道的所有DBMS引擎中的标准行为。

答案 1 :(得分:3)

您可能遇到以下情况:

  • 执行10个SQL语句
  • 回滚5个SQL语句
  • 执行10个SQL语句
  • 回滚12个SQL语句

实现这种性质的唯一方法是使用检查点。就InnoDB和事务处理而言,它们将被称为保存点。

虽然您有START TRANSACTION,COMMIT和ROLLBACK命令用于在单个事务中处理整个SQL语句块,但您必须在SQL语句组之间手动注入保存点。

示例:如果您运行以下交易顺序

  • INSERT 10行
  • SAVEPOINT savepoint1
  • UPDATE 3行
  • SAVEPOINT savepoint2
  • DELETE 7行
  • ROLLBACK TO SAVEPOINT savepoint1

结果是7个DELETE和3个UPDATE从InnoDB重做日志中消失了,但是10个INSERT仍然在日志中,可用于任何脏读,直到您执行以下操作之一:

  • COMMIT;
  • ROLLBACK;
  • RELEASE SAVEPOINT savepoint1
  • 在savepoint1
  • 之后引入额外的DML

在PHP或PDO中可能没有这样的支持机制,但MySQL / InnoDB确实有这样的SQL。

请阅读MySQL文档的此部分,了解如何运行SAVEPOINT and ROLLBACK TO SAVEPOINT. There is also info on removing savepoints without COMMIT or ROLLBACK going off

我刚刚阅读了Brian Fisher的评论,确实MySQL无法回滚表创建(Oracle可以)。实际上,任何表DDL都将提交任何未提交的数据并启动新事务。

答案 2 :(得分:1)

try{

  $pdo->beginTransaction(); 
  foreach($queries as $query)
    $result = $pdo->query($query);

  $pdo->commit();

}catch(PDOException $e){
  $pdo->rollBack();  
}