【发布时间】:2017-05-30 17:16:11
【问题描述】:
我有一个相当繁重的 SQL 搜索查询,需要几分钟才能完成,它是从一个由 ajax 请求调用的 PHP 脚本调用的。
问题是,用户经常因为不耐烦而多次点击搜索按钮,每次都会创建一个新的ajax请求,并执行一个新的PHP脚本。但旧的继续执行,即使连接已被删除。这会导致 SQL 服务器负载始终处于 100% 的 CPU 使用率。
所以我测试了我的理论,即即使关闭浏览器选项卡,脚本也会继续执行。我使用了 2 种类型的查询,即即席查询和存储过程执行,两种方法都做同样的事情,将数字 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 执行的方法,事务并不重要,因为它只是一个选择操作。
【问题讨论】:
-
也许在第一次点击后禁用按钮并显示其中一个旋转的 twidder 图像以让他们知道正在发生的事情,或者从任何旅游网站的剧本中获取一个页面并将它们重定向到另一个页面在他们等待时说“执行搜索”。
-
我有兴趣看看这是否可行。但另一种方法是使用会话变量来防止用户多次搜索。
-
这仅涵盖特定场景(多次单击同一查询),因为用户有时合法地需要修改他们的搜索查询,并且等待 > 1 分钟以完成第一个查询只是糟糕的用户体验
-
@iceman2992 如果是这种情况,您可以考虑只允许每个会话运行一个查询。如果您获取正在执行的查询的 SPID 并将其保存到会话变量中,那么您可以检查该会话变量中的值和
kill与该 SPID 相关的查询。 -
@iceman2992 查看this MSDN question 的答案。基本上只需在脚本开头查询
select @@spid即可获取SPID。将其保存到您的会话变量中。然后执行kill [spid]以取消该查询。我不知道您使用哪个库来进行查询,或者您的库是否支持 kill(我的 TSQL 工作是在 PHP 之外完成的,所以我不熟悉它的库),但这就是我想要的进入。
标签: php sql-server ajax