【问题标题】:What happens to a mysqli transaction when the connection is closed without a commit or rollback?当连接在没有提交或回滚的情况下关闭时,mysqli 事务会发生什么?
【发布时间】:2021-04-19 14:18:31
【问题描述】:

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

假设我有一些这样的代码(不管它的好坏做法):

# ... 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 连接将在事务启动后但在调用提交或回滚之前关闭。

交易是否也会立即被销毁/结束/无论是什么适当的期限,还是会保留并可能阻止来自其他服务的其他查询?

【问题讨论】:

  • 请分享更多细节。您想要涵盖的场景是什么?如果您的事务不包含更新或插入语句,那应该是什么问题?
  • 我想知道事务是否会在数据库端保持打开状态,因为它没有被显式提交或回滚,并可能阻止其他查询。
  • 你的代码很奇怪。它只begin_transaction() 一次,然后为每个单独的查询执行commit()。为什么要在这里使用事务?
  • 代码已被编辑得更直接一些,但这只是为了强调@KIKOSoftware 的可能情况的一个例子,而不是我们在生产中实际会遇到的情况。
  • 如果连接关闭,为什么要保持事务打开?

标签: php mysql mysqli


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2010-12-05
      • 1970-01-01
      • 2014-12-06
      • 2013-11-08
      • 2020-04-25
      • 1970-01-01
      • 1970-01-01
      • 2013-05-05
      • 2012-09-13
      相关资源
      最近更新 更多