mysqli_autocommit($con, false) 必须配合验证 select @@autocommit 返回0、确保表引擎为innodb、并在事务结束前显式调用commit/rollback,否则无效。

mysqli_autocommit() 必须设为 FALSE 才算真正关闭
很多人调用 mysqli_autocommit($con, false) 后仍发现 INSERT 立即生效,误以为函数没起作用。其实根本原因在于:MySQL 服务端的 @@autocommit 状态可能被连接池、中间件或历史配置覆盖,仅靠 PHP 层调用不保证生效。
验证是否真的关闭,执行一次查询:SELECT @@autocommit。返回 0 才表示成功;若返回 1,说明自动提交仍在运行,后续 mysqli_commit() 或 mysqli_rollback() 都不会生效。
- 必须在执行任何 DML(INSERT/UPDATE/DELETE)前调用
mysqli_autocommit($con, false) - 面向对象风格写法等价:
$mysqli->autocommit(false),效果一致 - 如果连接是复用的(如长连接、连接池),务必每次事务开始前重新确认并设置,不能假设上次状态延续
不支持事务的表类型会让 mysqli_autocommit 失效
mysqli_autocommit() 对 MyISAM、ISAM 等非事务型表完全无效——即使你成功调用了它,执行 INSERT 后立刻落盘,mysqli_rollback() 也什么都回滚不了,连报错都不会有。
常见错误现象:代码逻辑看起来完整(关 autocommit → 执行 SQL → 判断 → commit/rollback),但 rollback() 总是静默失败,查日志也没异常。
- 务必确认目标表引擎是
InnoDB:SHOW CREATE TABLE `websites`查看输出中的ENGINE=InnoDB - 建表时显式指定:
CREATE TABLE ... ENGINE=InnoDB,别依赖默认值 - MyISAM 表无法回滚不是 bug,是设计如此;换引擎是唯一解,没有兼容方案
事务未提交就断开连接,数据会丢失
调用 mysqli_autocommit($con, false) 后,所有修改都暂存在当前连接的事务上下文中。如果忘记 mysqli_commit($con),又直接 mysqli_close($con) 或脚本结束,MySQL 会自动回滚未提交的变更——这不是 PHP 的问题,是 MySQL 协议层行为。
更隐蔽的情况:PHP 脚本因超时、exit()、未捕获异常提前终止,也会触发隐式回滚。
- 务必把
mysqli_commit()和mysqli_rollback()放在try/catch的finally块里,或至少确保它们被执行 - 不要依赖“脚本自然结束”来清理事务;显式控制比假设更可靠
- 调试时可在
mysqli_commit()后加一句var_dump(mysqli_affected_rows($con))确认是否真提交了
autocommit 关闭后,start transaction 不需要再手动执行
有人照着 MySQL 命令行习惯,在 PHP 里先 mysqli_query($con, 'START TRANSACTION') 再关 autocommit,这是多余操作,甚至可能引发冲突。
MySQLi 在 autocommit = false 模式下,第一个 DML 语句(如 INSERT)会自动开启一个新事务;不需要、也不应该手动发 START TRANSACTION。
- 重复执行
START TRANSACTION可能导致嵌套事务警告(取决于 MySQL 版本和模式) - 如果用了
mysqli_begin_transaction()(PHP 7.0+),那就完全不用碰mysqli_autocommit(),两者是替代关系 - 老项目混用两种方式容易出状态混乱,选一种风格坚持到底
mysqli_autocommit(false) 就只是个摆设。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











