我正在修改我的一个应用程序的一些代码,最近将其从使用PHP ADODB库转换为PDO。在adodb中,一旦启动事务,在begin和commit命令之间的查询如果出现任何异常都会自动回滚。
PDO是否也是这样做的?如果在PDO中,在begin和commit之间的查询失败,方法会自动回滚事务,还是需要显式调用?
我正在修改我的一个应用程序的一些代码,最近将其从使用PHP ADODB库转换为PDO。在adodb中,一旦启动事务,在begin和commit命令之间的查询如果出现任何异常都会自动回滚。
PDO是否也是这样做的?如果在PDO中,在begin和commit之间的查询失败,方法会自动回滚事务,还是需要显式调用?
你需要自己调用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将自动回滚它们。
因此,根据您的应用程序情况(也许您有一个事件侦听器会为您提交?),该事务会被可能回滚。最好在异常发生的附近进行显式回滚。
来自http://www.php.net/manual/zh/pdo.transactions.php:
当脚本结束或连接即将关闭时,如果您有未完成的事务,则PDO将自动回滚。... 如果您没有显式提交事务,则假定出现了问题,因此为了数据安全起见执行回滚。
尽管如此,在发生错误的情况下,显式回滚事务是一种良好的实践。请参阅此问题以获取更多详细信息:如果PHP PDO事务失败,是否必须显式调用rollback()函数?
beginTransaction()
在try{...}
内部而不是外部。哪一个是正确的?在try{...}
之前还是之内? - veebeginTransaction()
过程中出现异常,你想要触发catch
块还是不触发?如果你的catch
块有一个调用rollBack()
的语句,你可能希望将beginTransaction()
放在try
之外,因为如果beginTransaction()
因异常失败,就没有活动事务可以回滚,导致catch
块的rollBack()
也会抛出异常。最好让原始异常冒泡。 - Adrian Wiik