如何在用户断开连接时停止PHP和SQL执行?

时间:2017-05-30 17:16:11

标签: php sql-server ajax

我有一个非常繁重的SQL搜索查询需要几分钟才能完成,从一个由ajax请求调用的PHP脚本调用。

问题是,用户经常会不耐烦地多次点击搜索按钮,每次创建新的ajax请求和新的PHP脚本执行。但旧的继续执行,即使连接已被删除。这会导致SQL Server负载持续处于100%的CPU使用率。

所以我测试了我的理论,即使浏览器选项卡关闭后脚本执行仍在继续。我使用了两种类型的查询,一种即席查询和一种存储过程执行,两种方法都做同样的事情,将数字1-9插入表中,每个数字之间有2秒的延迟。

即席查询:

for($i = 1; $i < 10; $i++){
    $sql = "INSERT INTO t (i) VALUES(?)";
    $res = pdoQuery($sql, array($i));
    if($res === false){
        echo $pdo->getErrorMessage();
        http_response_code(500);
        exit();
    }
    sleep(2);
}

SP电话:

$sql = "EXEC sp_Slow";
$res = pdoQuery($sql);
if($res === false){
    echo $pdo->getErrorMessage();
    http_response_code(500);
    exit();
}

我如何测试:使用触发ajax调用每个脚本的按钮,我测试了它们,点击按钮并立即关闭标签。然后监控表中的数据。就像我怀疑的那样,新数据每2秒插入一次。 (如果我直接在浏览器中打开脚本并关闭选项卡,而不是通过ajax请求它,也会发生这种情况)

我需要一种方法来在用户断开连接时完全杀死PHP和SQL执行,事务并不重要,因为它只是一个选择操作。

2 个答案:

答案 0 :(得分:0)

您可以使用php.ini指令或在运行时使用ignore_user_abort()函数更改此行为。

答案 1 :(得分:0)

这是我所做的,来自@Robbie Toyota的评论,谢谢!

if(!empty($_SESSION['SearchSPID'])){
    $sql = "KILL " . $_SESSION['SearchSPID'];
    $res = pdoQuery($sql);
    if($res === false){
        exit('Query error: failed to kill existing spid:' . $_SESSION['SearchSPID']);
    }       
    $_SESSION['SearchSPID'] = null;
}

$sql = "SELECT @@spid AS SPID";
$res = pdoQuery($sql);
$spid = $res->row_assoc()['SPID'];

$_SESSION['SearchSPID'] = $spid;

// do long query here

$_SESSION['SearchSPID'] = null;

当然使用这种方法你必须要小心会话文件锁定,如果发生这种情况会使整个事情变得毫无意义,因为那时请求将是顺序的而不是并行的