2016-07-26 13 views
0

は私のスクリプトです:PDOがrollBack()関数を実行する前にクエリをロールバックする方法はありますか?ここ

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

トランザクションは、すべての変更が一緒に発生することが重要であるか、まったく変更が発生しない場合に使用されます。

突然の停止(例えば、スクリプトが予期せず終了したり、サーバがクラッシュしたり、電源が切断されたりするなど)でDBの整合性を保つために、トランザクションの実装は、 commit()が呼び出されます。 execute中間クエリでは、変更は実際にデータベースに当たるわけではなく、limboで保持されます。あなたがコミットせずに終了すると、limboはちょうど投げ捨てられます。

rollBack()とすると、リムボウも放棄されます。

+0

大きな説明.. +1 – stack

+0

はい、この説明は正しいです。しかし、InnoDBが実際に内部で行っていることは、元のデータを "ロールバックセグメント"にコピーして、その場所のデータに更新を適用することです(ほとんどの変更をコミットすることを期待します)。ロールバックする場合、InnoDBはバックグラウンドで動作し、ロールバックセグメントに保存されているコピーをテーブルの元の場所に復元します。 –

+1

理由は、あなたが記述した "limbo"の概念は、トランザクションに含まれる可能性のある作業の量に制限がないので、変更を保持するためには膨大なものである必要があるからです。それは永続的に救われなければならない。これは、データがすでに保存されているため、最終的なコミットがかなり早いことを意味します。トランザクションの状態を更新するだけです。ロールバック・セグメント内の古いデータは、徐々にガーベジ・コレクションされます。 –

関連する問題