mysqli事务在insert失败时无法回滚
Posted
技术标签:
【中文标题】mysqli事务在insert失败时无法回滚【英文标题】:Mysqli transaction fail to rollback when insert is failed 【发布时间】:2021-10-03 19:58:18 【问题描述】:我有 3 个数据库,我需要创建数据库 A,然后创建数据库 B,然后创建链接数据库 A_B。
我在php中使用mysqli事务,有一个奇怪的情况(这是我第一次使用php事务),失败时它永远不会回滚,比如数据库A插入失败,但B仍然创建。和 A_B 创建不正确。
mysqli_begin_transaction($link);
try
$sql = "INSERT INTO A (
....)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?,?,?,?,?);";
$stmt = mysqli_prepare($link,$sql);
mysqli_stmt_bind_param($stmt,"sssssssssssss",
....
);
mysqli_stmt_execute($stmt);
$param_new_A_Rec = mysqli_insert_id($link);
for($i = 0; $i < $tot; $i++)
$sql = "INSERT INTO B (..)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?,?,?,?);";
$stmt = mysqli_prepare($link,$sql);
mysqli_stmt_bind_param($stmt,"ssssssssssss",
...
);
mysqli_stmt_execute($stmt);
$param_new_B_Rec = mysqli_insert_id($link);
$sql = "INSERT INTO A_B (
param_new_A_Rec,
param_new_B_Rec,
....
(?,?,?,?,?,?);";
$stmt = mysqli_prepare($link,$sql);
mysqli_stmt_bind_param($stmt,"ssssss",
....
);
mysqli_stmt_execute($stmt);
mysqli_commit($link);
catch (mysqli_sql_exception $exception)
mysqli_rollback($link);
throw $exception;
为什么如果 A 失败了,它永远不会命中 rollback() 并且它创建了不正确的 A_B 和 B 数据?我在这里错过了什么吗? 任何帮助将不胜感激!
【问题讨论】:
嘿,事务来自数据库而不是 PHP,看来你没有遗漏什么,你可以检查一下: 1. 一些MySQL DB Engines 不支持事务,在链接中是doc,您可以在其中检查您正在使用的那个是否支持它。 2.任何与mysqli_sql_exception
无关的错误都不会触发rollback
你好 Juan,引擎是 InnoDB。我有一个案例,当我将日期插入数据库 A 时,该字段是 tinyInt(),我按下“false”,它无法创建数据库 A,但它继续使用数据库 B 和数据库 A_B,外键链接不正确,这应该触发 mysqli_sql_exception 吗?
该引擎有支持,您尝试在catch
块中打印一些内容吗?看看它是否被捕获。
我错过了编辑。只是为了尝试,您可以将回滚放在不会产生影响的提交之前; false 作为数据类型可以被认为是0
,如果您在 AI 列中有以前的寄存器,mysqli_insert_id
将返回一个有效的 id。
请告诉我们:是否会引发异常?您是否启用了例外?此代码是否在命名空间内?如果创建了 B 和 A_B,你怎么知道 A 失败?听起来好像 A 成功完成了,否则你会得到异常。
【参考方案1】:
其实我需要加上这个
"mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);"
现在它正在捕获无效用例:
PHP 致命错误:未捕获的 mysqli_sql_exception:不正确的整数值:'' for column 'boolean_X' at row 1 in yourFile.php
【讨论】:
以上是关于mysqli事务在insert失败时无法回滚的主要内容,如果未能解决你的问题,请参考以下文章