Php 在用户中止时终止MySQL查询
从PHP运行长查询时,[如果用户在其浏览器中按stop键,如何终止查询? 考虑到我不能调用任何其他PHP函数,因为PHP在等待MySQL时被阻塞 此外,由于会话锁定,我无法再向服务器发出任何请求(通过Ajax) 因此,一个解决方案可以是:Php 在用户中止时终止MySQL查询,php,mysql,Php,Mysql,从PHP运行长查询时,[如果用户在其浏览器中按stop键,如何终止查询? 考虑到我不能调用任何其他PHP函数,因为PHP在等待MySQL时被阻塞 此外,由于会话锁定,我无法再向服务器发出任何请求(通过Ajax) 因此,一个解决方案可以是: 忽略用户中止 在后台运行长查询,让PHP每100毫秒检查一次是否完成 从查询中获取pid 如果用户中止,则终止pid 否则,完成后返回结果 我不知道该怎么做的两件事是: 运行非阻塞(后台)查询 获取查询的pid 一旦PHP注意到用户已停止请求(在脚本尝试
- 忽略用户中止
- 在后台运行长查询,让PHP每100毫秒检查一次是否完成
- 从查询中获取pid
- 如果用户中止,则终止pid
- 否则,完成后返回结果
- 运行非阻塞(后台)查询
- 获取查询的pid
更多关于连接处理的信息。我想你可以试试mysql
KILL
如果您能够通过user abort调用某些东西,那么您可以使用KILL
通过获取其进程id来终止mysql连接或查询
正如您在评论中所说,PHP将被阻止,直到mysql返回
因此,您可以通过以下方式从javascript获取帮助:
1.使用JS检测用户中止
2.在用户中止时调用函数
3.在该函数中,您可以终止上一个查询,但这里您需要上一个查询的进程id,这样您就可以通过一个技巧获得该id,即您可以在运行第一个长查询时选择进程id,并将其传递给JS函数,然后在终止您的查询时使用它
希望对您有所帮助。如果查询所花费的时间是因为返回的数据量太大,那么您可以使用
mysql\u unbuffered\u query
。然后在shutdown\u函数中
可以释放结果并断开与mysql的连接
如果您使用的是PHP5.3.x,并且拥有mysqlnd
,那么您可能可以在MYSQLI\u查询中使用MYSQLI\u ASYNC
,然后使用MYSQLI\u poll
获得结果
第一个选项仅在检索数据集花费时间的情况下有用。但是,如果mysql在解析和创建执行计划以及将表加载到内存方面确实花费了很长时间,那么它就不会有帮助。在这种情况下,您需要MYSQLI\u ASYNC
,它只能在php5.3.x
上使用mysqlnd
另外,如果您的主要问题是会话锁定
,请查看PHP文档中的这篇文章您可能会在这里找到一些有用的建议。在大多数情况下,PHP在尝试通过网络发送内容然后收到SIGPIPE之前,不会知道连接已关闭(因为用户已中止)。您唯一能做的就是尝试处理超时,中止长查询或从另一个进程终止它们 对于那些感兴趣的人,以下是我使用的:
<?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);
}
这是一个使用PDO的示例
$id=$connection->executeQuery(“选择连接_id()”)->fetchColumn();
忽略用户中止(true);
而($row=$result->fetch()){
/*处理*/
如果(连接被中止()){
$this->connection->executeQuery(“终止连接$id”);
打破
}
}
注意:注意多个连接,您可能会杀死错误的连接。问题不是连接处理,事实上,PHP在MySQL返回之前是被阻止的。我不知道我的答案是否对您有帮助,但如果您能找到任何解决方案,plz也会在这里发布。如果您有PHP5.3.x
和mysqlnd
使用mysqli\u查询
通过传递mysqli\u ASYNC
,您可以运行非阻塞查询。看看我的答案。@Peeyus,看看我的答案我用了什么问题是,我不能调用函数(或运行另一个查询),因为PHP被MySQL查询阻塞了。(即使使用Ajax,因为会话锁定)到目前为止回答得不错。我有一个使用MYSQLI\u ASYNC
运行的非阻塞查询,现在唯一的问题是,如何让PID终止?至于会话锁定,我想出于其他原因保持它的启用状态。好吧,算出了MYSQLI\u kill($MYSQLI,$MYSQLI->thread\u id)
@Petah很高兴你算出了。离开了一段时间,因此无法看到您的评论。所以,如果你觉得我的答案帮助你想出了一个解决方案,也许你可以把它标记为被接受的答案?这完全取决于你。所以它将以5秒的时间间隔持续轮询mysql服务器,对吗?@Peeyush,它将每1/2秒(500000微秒)轮询一次