PHP PDO 事务自动回滚

7

我正在修改我的一个应用程序的一些代码,最近将其从使用PHP ADODB库转换为PDO。在adodb中,一旦启动事务,在begin和commit命令之间的查询如果出现任何异常都会自动回滚。

PDO是否也是这样做的?如果在PDO中,在begin和commit之间的查询失败,方法会自动回滚事务,还是需要显式调用?

2个回答

19

你需要自己调用rollback(和commit),PDO不会为你执行。像这样:

$pdo = new \PDO(/* ... */);

$pdo->beginTransaction();

try {
    // do stuff..
} catch(\Throwable $e) { // use \Exception in PHP < 7.0
    $pdo->rollBack();
    throw $e;
}

$pdo->commit();

PDO会在脚本结束时回滚任何未完成的事务

当脚本结束或连接即将关闭时,如果存在未完成的事务,PDO将自动回滚它们。

因此,根据您的应用程序情况(也许您有一个事件侦听器会为您提交?),该事务会被可能回滚。最好在异常发生的附近进行显式回滚。


但是......如果您开始事务,进行一些插入和更新,然后进行 ALTER TABLE 操作,但失败的行大于1,则实际上默认操作是提交...MySQL 5.7。 - 18C
正确的,MySQL DDL查询(如ALTER TABLE,CREATE TABLE等)会创建一个隐式提交。https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html - chrisguitarguy
从PHP.net页面来看,beginTransaction()try{...}内部而不是外部。哪一个是正确的?在try{...}之前还是之内? - vee
@vee 你需要问自己的问题来回答这个问题: 如果在 beginTransaction() 过程中出现异常,你想要触发catch块还是不触发?如果你的catch块有一个调用rollBack()的语句,你可能希望将 beginTransaction() 放在try之外,因为如果beginTransaction() 因异常失败,就没有活动事务可以回滚,导致 catch 块的 rollBack() 也会抛出异常。最好让原始异常冒泡。 - Adrian Wiik

14

谢谢提供的信息,非常有趣,正是我所需要的。不知道为什么在文档中错过了它。再次感谢。 - jiraiya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接