mysql事务成功需综合判断:先检查每条dml语句的affected_rows是否符合预期,再捕获sql异常或错误信息,最后通过commit后验证性select确认业务状态。

MySQL 事务执行后如何确认是否成功提交
MySQL 事务本身没有“返回成功/失败”的显式状态值,COMMIT 执行成功只代表语句被接受,不等于数据已持久化或业务逻辑无误。真正判断事务是否成功,必须结合执行结果、错误码和后续验证。
检查 mysql_affected_rows() 或 mysqli::affected_rows 是否为 -1
这是最容易被忽略的信号:如果事务中某条语句(如 INSERT、UPDATE)实际影响行为 0 行,但没报错,COMMIT 仍会成功——可业务上可能已失败(比如更新了不存在的记录 ID)。
-
mysql_affected_rows()在 MySQLi 或 PDO 中对应mysqli_affected_rows()或$pdo->rowCount() - 对
SELECT、COMMIT、ROLLBACK等语句,该值通常为 -1,不能作为成功依据 - 关键点:应在每条 DML 语句后立即检查,而不是只看
COMMIT是否抛异常
捕获 mysqli_sql_exception 或检查 mysqli_error()
事务失败最常见原因是 SQL 错误(如外键冲突、唯一键重复、字段超长),这类错误在 COMMIT 前就已触发,但默认不抛出异常——除非开启异常模式。
- PDO:用
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)启用异常 - MySQLi:构造时传入
MYSQLI_REPORT_ALL,或调用mysqli_report(MYSQLI_REPORT_ALL) - 若未启用异常,必须手动调用
mysqli_error()检查上一条语句是否有错误字符串 - 注意:
COMMIT自身也可能失败(如死锁被选为牺牲者),此时mysqli_error()会返回类似"Deadlock found when trying to get lock"
用 SELECT 验证事务结果(尤其涉及业务约束时)
某些场景下,SQL 层面“成功”不代表业务正确。例如转账事务中,UPDATE account SET balance = balance - 100 WHERE id = 1 成功执行,但余额可能已为负——这需要应用层校验逻辑,而非依赖数据库返回。
- 在
COMMIT后立刻执行验证性SELECT,比如查目标记录最新值、关联计数、状态字段 - 避免在事务内做验证性
SELECT,否则看不到自己未提交的变更(除非用READ UNCOMMITTED,但不推荐) - 高并发下,验证和后续操作之间存在窗口期,必要时加
SELECT ... FOR UPDATE锁定关键行
真正的难点不在“怎么写 COMMIT”,而在于定义什么叫“成功”:是 SQL 语法通过?影响行数达标?约束未触发?还是业务状态符合预期?每个层级都需要对应的确认手段,漏掉任何一层都可能让错误静默发生。










