事务中的 Mysql 事务

2022-08-30 09:49:16

在处理 mysql 数据库的 PHP 脚本中,我最近需要在碰巧位于另一个事务内部的点上使用事务。我所有的测试似乎都表明这很好,但我找不到任何关于这种用法的文档。

我想确定 - 交易中的交易在mysql中是否有效?如果是这样,有没有办法找出嵌套事务中你有多少层?(即需要多少次回滚才能恢复正常)

提前致谢,布莱恩


答案 1

与其他人的答案相反,您可以在交易中有效地创建交易,这真的很容易。您只需创建 SAVEPOINT 位置并使用 ROLLBACK TO savepoint 回滚部分事务,其中 savepoint 是您为 savepoint 指定的任何名称。链接到MySQL文档:http://dev.mysql.com/doc/refman/5.0/en/savepoint.html 当然,事务中任何地方的查询都不应该是隐式提交的类型,否则整个事务将被提交。

例子:

START TRANSACTION;

# queries that don't implicitly commit

SAVEPOINT savepoint1;

# queries that don't implicitly commit

# now you can either ROLLBACK TO savepoint1, or just ROLLBACK to reverse the entire transaction.

SAVEPOINT savepoint2;

# queries that don't implicitly commit

# now you can ROLLBACK TO savepoint1 OR savepoint2, or ROLLBACK all the way.
# e.g.

ROLLBACK TO savepoint1;
COMMIT; # results in committing only the part of the transaction up to savepoint1

在PHP中,我编写了这样的代码,并且它完美地工作:

foreach($some_data as $key => $sub_array) {
  $result = mysql_query('START TRANSACTION'); // note mysql_query is deprecated in favor of PDO
  $rollback_all = false; // set to true to undo whole transaction
  for($i=0;$i<sizeof($sub_array);$i++) {
    if($sub_array['set_save'] === true) {
      $savepoint = 'savepoint' . $i;
      $result = mysql_query("SAVEPOINT $savepoint");
    }
    $sql = 'UPDATE `my_table` SET `x` = `y` WHERE `z` < `n`'; // some query/queries
    $result = mysql_query($sql); // run the update query/queries

    $more_sql = 'SELECT `x` FROM `my_table`'; // get data for checking
    $result = mysql_query($more_sql);
    
    $rollback_to_save = false; // set to true to undo to last savepoint
    while($row = mysql_fetch_array($result)) {
      // run some checks on the data
      if( /*some check says to go back to savepoint */) {
        $rollback_to_save = true; // or just do the rollback here.
      }
      if( /* some check says to rollback entire transaction */ ) {
        $rollback_all = true;
      }
    }
    if($rollback_all === true) {
      mysql_query('ROLLBACK'); // rollback entire transaction
      break; // break out of for loop, into next foreach
    }
    if($rollback_to_save = true) {
      mysql_query("ROLLBACK TO $savepoint"); // undo just this part of for loop
    }
  } // end of for loop
  mysql_query('COMMIT'); // if you don't do this, the whole transaction will rollback
}

答案 2

本手册的这一页可能会让您感兴趣:12.3.3。导致隐式提交的语句;引用几句话:

本节中列出的语句(以及它们的任何同义词)隐式结束事务,就好像在执行语句之前已经执行了一个操作一样。COMMIT

而且,在页面中再远一点:

事务控制和锁定语句。、 、 (如果值不是 1)、、 .BEGINLOCK TABLESSET autocommit = 1START TRANSACTIONUNLOCK TABLES

另请参阅此段落:

事务不能嵌套。
这是在发出语句或其同义词之一时对任何当前事务执行隐式操作的结果。commitSTART TRANSACTION


推荐