2016-07-26 36 views
0

这里是我的脚本:在执行rollBack()函数之前,PDO如何回滚查询?

try { 
    $dbh_con->beginTransaction(); 

     $stmt1 = $dbh_conn->prepare("UPDATE activate_account_num SET num = num + 1"); 
     $stmt1->execute(); 

     $stmt2 = $dbh_con->prepare("SELECT user_id FROM activate_account WHERE token = ?"); 
     $stmt2->execute(array($token)); 
     $num_rows = $stmt2->fetch(PDO::FETCH_ASSOC); 

     if ($num_rows['user_id']){ 
      $_SESSION['error'] = 'all fine'; 

     } else { 
      $_SESSION['error'] = 'token is invalid'; 
      header('Location: /b.php'); 
      exit(); 
     } 

    $dbh_con->commit(); 

    header('Location: /b.php'); 
    exit(); 

} catch(PDOException $e) { 

    $dbh_con->rollBack(); 

    $_SESSION['error'] = 'something is wrong'; 
    header('Location: /b.php'); 
    exit(); 
} 

正如你看到的,是else块包含exit()功能。所以当else块执行时,那么肯定rollBack();函数不会执行,因为在执行rollBack();之前,脚本会退出。但令人惊讶的是,UPDATE声明回滚..如何?

回答

1

在正常情况下,当客户端脚本退出时,php客户端会断开连接并导致MySQL中的回滚。

3

当所有更改一起发生,或根本没有更改发生时很重要。

为了在发生突然停止时保持数据库的完整性(例如:脚本意外退出,服务器崩溃,电源被切断......),事务的实现将保持您的保护,直到不做任何更改调用commit()。当您中介查询execute时,更改实际上并未到达数据库,而是处于不正常状态。如果你没有提交就退出,这个僵尸就会被扔掉。

当你rollBack(),limbo也刚刚扔掉。

+0

很好的解释.. +1 – stack

+0

是的,这个解释在概念上是正确的。但是值得一提的是,InnoDB在内部真正做的是将原始数据复制到“回滚段”,将更新应用到数据中(预计您将承担大部分更改)。如果您执行回滚,InnoDB将在后台运行,以将保留在回滚段中的副本恢复到表中的原始位置。 –

+1

原因是您所描述的“limbo”概念对于变更需要巨大的努力,因为交易中可能的工作量没有限制。它必须持久保存。这意味着您的最终COMMIT非常快,因为数据已经保存。它只需更新交易的状态。回滚段中的过时数据逐渐被垃圾收集。 –

相关问题