一尘不染

在用户中止时终止MySQL查询

mysql

从PHP运行长查询时, [如果用户在浏览器中按Stop,我如何杀死查询?

考虑到我不能调用任何其他PHP函数,因为在等待MySQL时PHP被阻止了。

另外,由于会话锁定,我无法再通过Ajax向服务器发出任何请求。

因此,一种解决方案可能是:

  • 忽略用户中止
  • 在后台运行长查询,并让PHP每100毫秒检查一次是否完成
  • 从查询中获取pid
  • 如果用户中止,请杀死该pid
  • 否则返回结果

我不知道该怎么做的两件事是:

  • 运行非阻塞(后台)查询
  • 获取查询的pid

阅读 298

收藏
2020-05-17

共1个答案

一尘不染

对于那些感兴趣的人,这是我使用的:

<?php
// Connection to query on
$query_con = mysqli_connect($host, $user, $password, $name, $port);

// Connection to kill on
$kill_con = mysqli_connect($host, $user, $password, $name, $port);

// Start the query
$query_con->query($slow_query, MYSQLI_ASYNC);

// Get the PID
$thread_id = $query_con->thread_id;

// Ignore user abort so we can kill the query
ignore_user_abort(true);

do  {
    // Poll MySQL
    $links = $errors = $reject = array($mysqli->mysqli);
    $poll = mysqli_poll($links, $errors, $reject, 0, 500000);

    // Check if the connection is aborted and the query was killed
    if (connection_aborted() && mysqli_kill($kill_con, $thread_id)) {
        die();
    }
} while (!$poll);

// Not aborted, so do stuff with the result
$result = $link->reap_async_query();
if (is_object($result)) {
    // Select
    while ($row = $result->fetch_object()) {
        var_dump($row);
    }
} else {
    // Insert/update/delete
    var_dump($result);
}
2020-05-17