这似乎是一个足够简单的问题,但我找不到任何特定于 MySQL 的明确答案。看这个:
$mysqli->autocommit(false); //Start the transaction
$success = true;
/* do a bunch of inserts here, which will be rolled back and
set $success to false if they fail */
if ($success) {
if ($mysqli->commit()) {
/* display success message, possibly redirect to another page */
}
else {
/* display error message */
$mysqli->rollback(); //<----------- Do I need this?
}
}
$mysqli->autocommit(true); //Turns autocommit back on (will be turned off again if needed)
//Keep running regardless, possibly executing more inserts
问题是,我见过的大多数例子只是在提交失败时结束脚本,要么让它完成,要么显式调用exit()
,这显然会自动回滚事务(?),但是如果我需要继续运行并可能稍后执行更多数据库更改操作怎么办?如果此提交失败并且我没有回滚,则会重新打开自动提交(根据this http://php.net/manual/en/mysqli.autocommit.php#79103对 PHP 手册条目的评论autocommit
does提交挂起的操作)或者甚至显式调用另一个$mysqli->commit()
稍后,尝试再次提交以前的插入,因为之前失败并且它们没有回滚?
我希望我已经说得足够清楚了,并且我可以得到一个明确的答案,这个问题一直困扰着我。
编辑:好吧,也许我在那行评论中表达了错误的问题。这其实不是我是否做的问题need回滚,正如所指出的,这将取决于我的用例,但实际上效果如何该行是否有回滚。也许一个更简单的问题是:失败了吗?commit
调用会丢弃挂起的操作,还是只是将它们保留在挂起状态,等待回滚或另一次提交?
如果您不重复使用连接并且在事务失败后立即关闭连接,则关闭连接无论如何都会导致隐式回滚。
如果您要重新使用连接,则绝对应该进行回滚以避免与任何后续语句不一致。
如果您没有真正重复使用它,但它仍然处于阻塞状态(例如,保持打开状态几秒钟甚至几分钟,具体取决于您是否在网站上或 cronjob 上),请记住可能有许多并发连接正在进行。因此,如果您有一个非常大的事务,服务器需要将其保持在临时状态,这可能会消耗大量内存(例如,如果您正在进行影响大量列或表的主要数据库迁移),您绝对应该显式执行失败后回滚或关闭连接以进行隐式回滚。
另一个因素是=>如果您在不同的进程中有大量并发连接,它们可能会也可能不会看到事务的部分内容,即使事务尚未提交,具体取决于您正在使用的事务隔离级别。也可以看看:https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)