You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP mysqli的begin_transaction与commit事务回滚失效问题

事务未生效的核心原因

MySQLi 扩展不会在单条SQL执行失败时自动回滚已开启的事务,你当前的代码没有对每条SQL的执行结果做校验,无论中间语句是否报错,最后都会强制执行commit(),自然会把之前执行成功的第一条插入语句提交落库。
另外要先确认基础前提:你操作的categories表必须使用支持事务的存储引擎(如InnoDB),如果用的是MyISAM等不支持事务的引擎,所有事务相关语句都不会生效,SQL执行后会直接持久化。

正确实现原子性事务的方案

逐次校验事务内每一条SQL的执行结果,只要任意一条执行失败,立刻调用rollback()方法撤销事务内所有已完成的操作,终止后续流程;只有所有SQL全部执行成功时,才调用commit()提交事务。
推荐开启MySQLi的异常报错模式,用try/catch结构捕获错误,避免手动判断返回值出现遗漏:

<?php
// 开启MySQLi严格错误模式,SQL执行出错时直接抛出异常
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$connection = mysqli_connect("数据库地址", "数据库用户名", "数据库密码", "数据库名");

try {
    // 开启事务
    $connection->begin_transaction();

    // 执行第一条插入语句
    mysqli_query($connection, "INSERT INTO categories (name) VALUES ('{}')");
    // 执行第二条插入语句,你测试时写的错误SQL执行到这里会直接抛出异常
    mysqli_query($connection, "IINSERT INTO categories (name) VALUES ('{}')");

    // 所有语句执行无异常,提交事务持久化数据
    $connection->commit();
    echo "数据批量插入成功";
} catch (mysqli_sql_exception $e) {
    // 捕获到SQL执行错误,回滚事务内所有操作
    $connection->rollback();
    echo "插入失败,已回滚所有未提交操作,错误原因:" . $e->getMessage();
}
?>
注意事项
  • 事务内不要执行CREATE、ALTER、DROP这类DDL语句,这类语句会触发隐式提交,导致回滚失效。
  • 事务的开启、语句执行、提交/回滚必须在同一个数据库连接实例中完成,跨连接的操作不属于同一个事务上下文,无法保证原子性。
  • 如果不使用异常模式,必须在每次调用mysqli_query()后判断返回值是否为false,一旦返回false立刻执行回滚,不能继续执行后续语句也不能直接走提交逻辑。

内容的提问来源于stack exchange,提问作者Taha Sami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.16 23:21:21