当连接在没有提交或回滚的情况下关闭时,mysqli 事务会发生什么?

What happens to a mysqli transaction when the connection is closed without a commit or rollback?

相关问题,但不是我想知道的,因为我很好奇 PHP mysqli lib/functions:[=16= 的具体行为]

假设我有这样的代码(不管它是好是坏):

# ... some code

$conn = new mysqli('localhost', 'widget-manager', 'secret-widgets', 'widgets');
$conn->begin_transaction(MYSQLI_TRANS_START_READ_WRITE);
if (false) {
    $sql = "UPDATE widgets SET widget_num = 1 WHERE widget_id = 5";
    $res = $conn->query($sql);
    if ($res) {
        $conn->commit();
    } else {
        $conn->rollback();
    }
}
$conn->close();

# ... some more code

将跳过包含提交和回滚的 if,并且 mysqli 连接将在事务开始后但在调用提交或回滚之前关闭。

事务是否也会立即 destroyed/ended/whatever-the-proper-term,还是会保留并可能阻止来自其他服务的其他查询?

如果客户端断开连接,MySQL 服务器会清理会话。这将回滚任何未提交的事务、释放行锁和 table 锁、删除临时 table 和会话变量等

使用哪个客户端接口没有区别(mysqli vs. PDO vs. Java vs. 任何东西)。

当您调用 begin_transaction() 或将 autocommit 值设置为 0 时,您实际上是在告诉 MySQL 服务器 “在我明确表示之前不要提交数据告诉你。当您编写从不调用提交的代码时,服务器上的数据将永远不会提交。

当你调用mysqli::close()如果PHP脚本结束,那么mysqlnd(或libmysql)将发送COM_QUIT命令到服务器。然后服务器将关闭会话并丢弃与其相关的任何数据,包括打开的事务、锁或准备好的语句句柄。 MySQL 服务器还应遵循 wait_timeout 设置,以防 PHP 脚本崩溃并且命令永远不会发送。

mysqli 特有的一件事是持久连接。这些连接在 PHP 次执行之间重复使用。它们通常被认为是搬起石头砸自己脚的好方法,这就是为什么 mysqli 有一些逻辑来帮助解决这个问题。您可以使用名为 rollback_on_cached_plink 的 INI 设置来指示 mysqli 在脚本结束时通过发出回滚命令来清理持久连接。