use*_*084 8 mysql database pdo
我正在使用PDO,用户应该可以选择停止之前触发的请求.
例如,现在我单击生成报告,但是在请求之后我忘了再选择一个使报告无效的字段.所以我需要取消请求,并创建一个新请求.
基本上,如何取消正在运行的MYSQL查询?
if (!isset($_POST['cancel_request'])) {
//query
}else{
//the user cancel the query
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用kill命令和PID进程,但这应该通过PDO运行,我不知道什么是PID.
这里的主要问题是在生成报告的异步请求和应该停止它的脚本之间共享PID.
您可以使用以下方式获取PID:
$stmt = $dbh->prepare("SELECT CONNECTION_ID()");
$stmt->execute();
$pid = $stmt->fetchColumn();
Run Code Online (Sandbox Code Playgroud)
你可以使用php-shared-memory之类的东西在你的脚本之间创建一个共享变量.如果您没有将Composer用于项目依赖项,则此库具有独立版本(此处为 1.5.0 ).
实施样本:
<?php
if (!include __DIR__ . '/vendor/autoload.php')
{
die('You must set up the project dependencies.');
}
use Fuz\Component\SharedMemory\SharedMemory;
use Fuz\Component\SharedMemory\Storage\StorageFile;
// your intializations here
$storage = new StorageFile("/tmp/shared.{$user_id}.sync");
$shared = new SharedMemory($storage);
if (!isset($_POST['cancel_request']))
{
$stmt = $dbh->prepare("SELECT CONNECTION_ID()");
$stmt->execute();
$pid = $stmt->fetchColumn();
$shared->pid = $pid;
// your long query here
$shared->destroyStorage();
}
else
{
// kills pid
$pid = $shared->pid;
if (!is_null($pid))
{
$dbh->exec("KILL {$pid}");
}
}
Run Code Online (Sandbox Code Playgroud)
正如其他人提到的,您可以登录到您的 MySQL 服务器,发出SHOW PROCESSLIST,找到要放弃的查询的编号,然后发出KILL number命令。
似乎您希望此功能为您的报告设计用户提供自助服务,而不是让他们打电话给您的网络操作人员并要求他们这样做,或者教他们使用管理工具。
我以前做过这样的事情。它需要三个部分。
首先,您需要安排将标签插入到您的用户可能想要放弃的查询类型中。例如,如果您的用户正在执行此操作
SELECT cust_id, SUM(orders), COUNT(orders)
FROM big_fat_table
GROUP BY cust_id
Run Code Online (Sandbox Code Playgroud)
您需要更改查询的文本,使其在注释中嵌入一个标记,例如像这样。
SELECT /*report:user2290084*/ cust_id, SUM(orders), COUNT(orders)
FROM big_fat_table
GROUP BY cust_id
Run Code Online (Sandbox Code Playgroud)
请注意,此标签中有两个项目:report:和一个用户 ID。用户 ID 必须与运行查询的连接无关——如果您试图放弃在其上运行的查询,则该连接将被捆绑。标签根本不影响查询的执行。它只是显示在服务器的进程表中。
第二:运行这些查询的 PDO 代码将需要良好且用户友好的异常处理,因为在您的代码下面炸毁查询将成为例行公事。您将需要对此进行试验,以使这种放弃查询功能对您的用户有用。
第三:当你需要放弃user2290084的报表查询时发出这个查询
select id from information_schema.processlist where info like '%/*%report:user2290084*/%'
Run Code Online (Sandbox Code Playgroud)
它查看进程列表以查找带有适当标记的查询的进程 ID。然后发出
kill <<that process id>>
Run Code Online (Sandbox Code Playgroud)
你已经放弃了查询。
在 php 中,它可能是这样的:
$q = 'select id from information_schema.processlist where info like :tag';
$tag = '%/*report:' . $userid . '*/%'
$stmt = $dbh->prepare($q);
$stmt->bindParam(':tag', $tag);
$stmt->execute();
$pids = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);
foreach ($pid in $pids) {
$dbh->query('KILL ' . $pid);
}
Run Code Online (Sandbox Code Playgroud)
注意这段代码中有一个循环。您可能会为此用户运行多个报告查询,也可能没有。