信息发布→ 登录 注册 退出

如何正确使用 MySQLi 事务实现插入失败自动回滚

发布时间:2025-12-25

点击量:

当多个 insert 操作需满足“全成功或全失败”时,必须结合 try/catch 捕获异常,并在出错时显式调用 rollback();仅调用 begin_transaction() 和 commit() 无法自动回滚失败语句。

MySQLi 的事务机制本身不会自动感知 SQL 语法错误或约束冲突——mysqli_query() 遇到非法语句(如 IINSERT)时默认返回 false,但不会抛出异常,除非你启用异常模式。因此,原代码中即使第二条 SQL 因拼写错误执行失败,commit() 仍会被无条件调用,导致第一条合法插入被永久提交,违背原子性要求。

✅ 正确做法是:启用 MySQLi 异常模式 + try/catch + 显式 rollback。需在连接后设置 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT),使所有错误触发 mysqli_sql_exception:

begin_transaction();

    // 这条会成功
    mysqli_query($connection, "INSERT INTO categories (name) VALUES ('Electronics')");

    // 这条因表名/语法错误触发异常(如 IINSERT → INSERT 拼错)
    mysqli_query($connection, "IINSERT INTO categories (name) VALUES ('Books')");

    // 仅当全部成功才提交
    $connection->commit();
    echo "✅ 所有插入成功完成。";
} catch (mysqli_sql_exception $e) {
    // 任一语句失败即回滚整个事务
    $connection->rollback();
    echo "❌ 事务已回滚。错误:" . $e->getMessage();
}
?>

⚠️ 注意事项:

  • 必须调用 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT),否则 mysqli_query() 失败仅返回 false,不会进入 catch 块;
  • rollback() 必须在 catch 中显式调用,PHP 不会自动回滚;
  • 事务仅对支持事务的存储引擎(如 InnoDB)生效,MyISAM 不支持;
  • 避免在事务中执行非数据库操作(如文件写入、HTTP 请求),因其无法回滚。

? 总结:事务的原子性不是自动保障的,而是依赖开发者主动检查执行结果并协调 commit()/rollback()。启用严格异常模式 + 结构化异常处理,是确保数据一致性的关键实践。

标签:# 这条  # 结构化  # 仍会  # 抛出  # 因其  # 第二条  # 第一条  # 不支持  # 并在  # 多个  # mysql  # http  # 数据库  # mysqli  # catch  # try  # sql  # go  # php  
在线客服
服务热线

服务热线

4008888355

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!