Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当用户断开连接时,如何停止PHP和SQL执行?_Php_Sql Server_Ajax - Fatal编程技术网

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

当用户断开连接时,如何停止PHP和SQL执行?,php,sql-server,ajax,Php,Sql Server,Ajax,我有一个相当繁重的SQL搜索查询,需要几分钟才能完成,它是从一个由ajax请求调用的PHP脚本调用的 问题是,用户常常因为不耐烦而多次单击搜索按钮,每次都会创建一个新的ajax请求和一个新的PHP脚本执行。但是,即使连接已断开,旧的连接仍将继续执行。这会导致SQL server负载始终保持100%的CPU使用率 因此,我测试了我的理论,即即使关闭浏览器选项卡,脚本仍会继续执行。我使用了两种类型的查询,即席查询和存储过程执行,两种方法都做相同的事情,将数字1-9插入表中,每个数字之间有2秒的延迟

我有一个相当繁重的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);
}
如何测试:使用触发对每个脚本的ajax调用的按钮,我通过单击按钮并立即关闭选项卡来测试它们。然后监视表中的数据。正如我所怀疑的,每2秒就会插入新数据。(如果我直接在浏览器中打开脚本并关闭选项卡,而不是通过ajax请求脚本,也会发生这种情况)


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

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

以下是我所做的,来自@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;

当然,使用这种方法时,您必须小心会话文件锁定,如果发生这种情况,整个过程将变得毫无意义,因为这样,请求将是连续的,而不是并行的

可能在第一次单击后禁用按钮并显示其中一个旋转的twidder图像,让他们知道正在发生什么,或者从任何旅游网站的playbook中获取一个页面,并将其重定向到另一个显示“正在执行搜索”的页面在他们等待的时候。我很想看看这是否可行。但另一种方法是使用会话变量来阻止用户多次搜索。这只涉及特定场景(多次单击同一查询),因为用户有时需要合法地修改其搜索查询,而等待第一个查询完成时间>1分钟只会很糟糕UX@iceman2992如果是这样的话,您可以研究每个会话只允许运行一个查询。如果获取正在执行的查询的SPID并将其保存到会话变量中,则可以检查该会话变量中的值并
kill
与该SPID相关的查询。@iceman2992查看的答案。基本上,只需在脚本开始处查询
选择@spid
,即可获得spid。将其保存到会话变量中。然后执行
kill[spid]
以取消该查询。我不知道您使用哪个库进行查询,或者您的库是否支持kill(我的TSQL工作是在PHP之外完成的,所以我不熟悉它的库),但这就是我要研究的内容。通过AJAX调用执行的PHP脚本能否确定用户是否中止了脚本的执行?我相信OP主要关心的是停止查询的执行。刚刚测试过,不起作用,我添加了
ignore\u user\u abort(false)位于脚本的顶部,并显示相同的行为observed@iceman2992请看这里:OP似乎在使用sql server,而不是mysql。@JonathanKuhn但逻辑是一样的。您基本上从服务器获取进程ID,然后杀死该进程。SQL Server在这方面的工作方式与MySQL相同。编辑:我的坏;我本应该考虑比第一个答案看得更远。谢谢你为后代发布你的解决方案。它有用吗?我只是想知道PDO是否支持sql server的
kill
。此外,正如@N.B.所提到的,您应该检查您的搜索查询以加快搜索速度。如果您正确使用索引,并且没有返回/处理大量数据,那么查询不应该花费几分钟的时间。是的,它确实有效,是的,我也在尝试优化查询。
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;