0

I got stuck with this problem, I found many posts but seemed it's not useful. So I post again here and hope someone can help me.

Let say I have 2 button, 1 is Start button and 1 is Stop button. When I press start will call ajax function which query very long time. I need when I press Stop will stop immediately this query, not execute anymore.

this is function used to call query and fetch row. (customize Mysqli.php)

public function fetchMultiRowset($params = array()) {
    $data = array();
    $mysqli = $this->_adapter->getConnection();
    $mysqli->multi_query($this->bindParams($this->_sql, $params));
    $thread_id = mysqli_thread_id($mysqli);
    ignore_user_abort(true);
    ob_start();
    $index = 0;
    do {
        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
                $data[$index] = $row;
                $index++;
                echo " ";
                ob_flush();
                flush();
            }
            $result->free();
        }
    }
    while ($mysqli->more_results() && $mysqli->next_result());
    ob_end_flush();
    return $data;
}

Function in Model:

public function select_entries() {
    $data = null;
    try {
        $db = Zend_Db_Adapter_Mysqlicustom::singleton();
        $sql = "SELECT * FROM report LIMIT 2000000";
        $data = $db->fetchMultiRowset($sql);
        $db->closeConnection();
    } catch (Exception $exc) {
    }
    return $data;
}

Controller:

public function testAction(){
    $op = $this->report_test->select_entries();
}

In AJAX I used xhr.abort() to stop the AJAX function. But it still runs the query while AJAX was aborted.

How do I stop query? I used Zend Framework.

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
sontd
  • 397
  • 2
  • 4
  • 15

1 Answers1

2

EDIT: I did not look in detail at your program, now I see that not the query itself is taking so long, but the reading of all the data. So just check every 1000 rows, if the ajax call is still active. Ajax Abort.

Solution in case of a long-running SQL-query:

You would have to allow the application to kill database queries, and you need to implement a more complex interaction between Client and Server, which could lead to security holes if done wrong.

The Start-Request should contain a session and a page id (secure id, so not 3 and 4 and 5 but a non-guessable but unique hash of some kind). The backend then connects this id with the query. This could be done in some extra table of the database, but also via comments in the SQL query, like "Session fid98a08u4j, Page 940jfmkvlz" => s:<session>p:<page>.

/* s:fid98a08u4jp:940jfmkvlz */ select * from ...

If the user presses "stop", you send session and page id to the server. The php-code then fetches the list of your running SQL Queries and searches for session and page and extracts the query id.

Then the php sends a

kill query <id>

to the MySQL-server.

This might lead to trouble when not using transactions, and this might damage replication. And even a kill query might take some time in the state 'killing'.

So be sure that you can and want not to split the long running query into subqueries, which check if the request is still valid every few seconds, or that you do not just want to kill the query for cosmetical reasons.

Community
  • 1
  • 1
flaschenpost
  • 2,205
  • 1
  • 14
  • 29