通八洲科技

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

日期:2025-12-25 00:00 / 作者:碧海醫心

当多个 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();
}
?>

⚠️ 注意事项:

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