PDO交易api如何运作?

时间:2016-07-15 21:39:05

标签: php mysql pdo transactions

这是我的代码结构:

// db connection here

try {
    $dbh_conn->beginTransaction();

    $stm = $dbh_conn->prepare("SELECT user_id FROM resend_pass WHERE token = ?");
    $stm->execute(array('value'));
    $num_rows = $stm->fetch(PDO::FETCH_ASSOC);

    if($num_rows) {
        echo 'one'; die;

    } else {
        echo 'two'; die;

    }

    $dbh_conn->commit();

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

    echo 'three'; die;

}

何时执行该查询?你知道,我的脚本完全符合预期。但我想知道怎么样?如您所见,if - else之前有一个commite()声明;此外,ifelse的块中都有die;。据我所知,这条线永远不会执行:

$dbh_conn->commit();

因为它前面有一个die。但令人惊讶的是我的代码也可以运行。以下是所有可能的输出:

  • 如果one作为value表格中的标记存在,则会打印resend_pass
  • 如果twovalue表中没有作为令牌存在,则会打印resend_pass
  • 如果出现错误,则会打印three (如语法SQL错误)

请参阅?一切都很好。但是怎么样?何时执行commit()函数?在那些die之前?

注意: resend_pass的引擎是 innoDB

1 个答案:

答案 0 :(得分:1)

在调用execute()时执行查询(请注意query()调用execute())。

如果查询更改了支持事务的表中的数据,则在释放PDO对象时将回滚更改,因为该对象超出范围或脚本终止并清除。这是由于PDO代码,而不是MySQL。

如果查询更改了不支持事务的表中的数据(例如MyISAM表),则更改在执行时是永久性的,并且无法回滚。

有一些SQL statements that perform an implicit commit。即使您的脚本在调用commit()之前死亡,它们也会在执行后立即成为永久性的。

正如@MarcB所提到的,您的示例显示了只读SELECT语句。如果您使用INSERT / UPDATE / DELETE,则会更容易测试行为。