MySQLi事务遇错误后savepoint全部丢失,无法回滚求助
MySQLi事务中错误查询导致保存点消失的原因及解决办法
这不是MySQLi的问题,本质是MySQL InnoDB存储引擎的事务默认行为。
核心原因
当事务中执行了一条产生语句级错误(比如你这里重复创建已存在的表)的SQL时,InnoDB不会立即终止整个事务,但会自动清除当前事务内所有已创建的保存点。此时事务进入"部分失败"状态,保存点机制不再可用,后续执行ROLLBACK TO SAVEPOINT自然会提示"保存点不存在"。
而你后续执行的commit()会提交事务中所有之前成功执行的语句,也就是三条INSERT操作,这就是最终三条数据都被提交的原因。
你的代码问题点
你在执行错误的CREATE TABLE语句后,没有检查SQL执行是否成功就继续执行回滚到保存点的操作,忽略了错误已经导致保存点失效的事实。
解决方案
执行每一条SQL后都必须检查错误,一旦发现错误,根据业务需求选择:
- 直接回滚整个事务(放弃所有操作);
- 若需要继续事务,此时已无保存点可用,只能继续执行后续语句或手动重新创建保存点(但不推荐,因为事务已处于部分失败状态)。
修改后的示例代码:
$mysqli = new mysqli($_HOST, $_USER, $_PASS, $_DB_NAME); // 替换为你的数据库凭证 $mysqli->begin_transaction(); $mysqli->savepoint("SP1"); if (!$mysqli->query("INSERT INTO Users (Username, FavouriteColour) VALUES ('Alice', 'Red');")) { $mysqli->rollback(); die("插入Alice失败:" . $mysqli->error); } $mysqli->savepoint("SP2"); if (!$mysqli->query("INSERT INTO Users (Username, FavouriteColour) VALUES ('Bob', 'Green');")) { $mysqli->rollback(); die("插入Bob失败:" . $mysqli->error); } $mysqli->savepoint("SP3"); if (!$mysqli->query("INSERT INTO Users (Username, FavouriteColour) VALUES ('Charlie', 'Blue');")) { $mysqli->rollback(); die("插入Charlie失败:" . $mysqli->error); } // 执行错误语句时检查错误 if (!$mysqli->query("CREATE TABLE Users (ID INT AUTO_INCREMENT NOT NULL PRIMARY KEY, Username VARCHAR(255), FavouriteColour VARCHAR(64));")) { // 发现错误,直接回滚整个事务 $mysqli->rollback(); die("建表失败:" . $mysqli->error); } // 若前面无错误,再执行回滚到保存点 if (!$mysqli->query("ROLLBACK TO SAVEPOINT SP2")) { $mysqli->rollback(); die("回滚到SP2失败:" . $mysqli->error); } $mysqli->commit();
内容的提问来源于stack exchange,提问作者user9214088
相关产品推荐
相关产品推荐

