Kill MySQL query on user abort

后端 未结 6 1423
星月不相逢
星月不相逢 2020-12-05 03:30

When running a long query from PHP, [how] can I kill the query if the user presses stop in their browser?

Take into consideration that I cannot call

相关标签:
6条回答
  • 2020-12-05 03:58

    PHP, in most cases, won't know that a connection was closed (since the user aborted) until it tries to send something over the network and then receives a SIGPIPE. The only thing you can do is try working with timeouts aborting to long queries or killing them from another process.

    0 讨论(0)
  • 2020-12-05 03:59

    This is an example of doing it with PDO.

    $id = $connection->executeQuery("SELECT CONNECTION_ID()")->fetchColumn();
    ignore_user_abort(true);
    while($row = $result->fetch()) {
      /* Processing ... */
      if (connection_aborted()) {
        $this->connection->executeQuery("KILL CONNECTION $id");
        break;
      }
    }
    

    Note: Keep an eye out for multiple connections, you may kill the wrong one.

    0 讨论(0)
  • 2020-12-05 04:04

    i think you can give a try to mysql KILL

    http://dev.mysql.com/doc/refman/5.0/en/kill.html

    if you are able to call something over user abort then you can use KILL to kill you mysql connection or query by fetching it's process id.

    And as you said in your comment that PHP is blocked until mysql returns

    so you can take help from javascript in this way:

    1.detect the user abort using JS 2.call a function on user abort 3.in that function you can kill you previous query but here you need the process id of the previous query so you can get that by a trick that you can select the process id when you run you first long query and pass it to JS function and use it in killing you query.

    Hope it will help you.

    0 讨论(0)
  • 2020-12-05 04:06

    Once PHP notices the user has stopped the request (this usually will not happen until the script tries to output something to the user), your script will terminate. Before shutting down, PHP calls any shutdown functions you've activated. You can implement a shutdown function that kills your query, and register it with register_shutdown_function()

    An other way you might be able to do this, is by running your script with ignore_user_abort() turned on, and checking if the user has aborted by calling connection_aborted() periodically. If the user has aborted, kill the query and gracefully exit your script.

    More information on connection handling here.

    0 讨论(0)
  • For those who are interested, here is what I used:

    <?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);
    }
    
    0 讨论(0)
  • 2020-12-05 04:10

    If the time taken by query is because of the large dataset returned, then you can use mysql_unbuffered_query. And then in shutdown_function you can free the result and disconnect form mysql.

    And if you are using PHP 5.3.x and have mysqlnd you can probably use MYSQLI_ASYNC in mysqli_query and then use mysqli_poll to get the result.

    The first option will only help in case of time taken in retrieval of dataset. But if the mysql is actually taking a long time in parsing and creating the execution plan and loading tables to memory it wont help. In that case you need MYSQLI_ASYNC which is only available on PHP 5.3.x WITH mysqlnd.

    Also if your main problem is session locking have a look at this post on PHP's documentation http://php.net/manual/en/ref.session.php#64525
    You might find some helpful advice there.

    0 讨论(0)
提交回复
热议问题