mysqli::poll

mysqli_poll

(PHP 5 >= 5.3.0,PHP 7,PHP 8)

mysqli::poll -- mysqli_poll轮询连接

描述

面向对象风格

public static mysqli::poll(
    ?array &$read,
    ?array &$error,
    array &$reject,
    int $seconds,
    int $microseconds = 0
): int|false

过程化风格

mysqli_poll(
    ?array &$read,
    ?array &$error,
    array &$reject,
    int $seconds,
    int $microseconds = 0
): int|false

轮询连接。该方法可以用作 静态 方法。

注意:

仅在使用 mysqlnd 时可用。

参数

read

要检查其是否有可读的未完成结果的连接列表。

error

发生错误的连接列表,例如查询失败或连接丢失。

reject

被拒绝的连接列表,因为没有运行异步查询,函数无法为其轮询结果。

seconds

最大等待秒数,必须是非负数。

microseconds

最大等待微秒数,必须是非负数。

返回值

成功时返回就绪的连接数,否则返回 false

错误/异常

当未传递 readerror 参数时,会抛出一个 ValueError 异常。

变更日志

版本 描述
8.3.0 现在当未传递 readerror 参数时,会抛出一个 ValueError 异常。

示例

示例 #1 一个 mysqli_poll() 示例

<?php
$link1
= mysqli_connect();
$link1->query("SELECT 'test'", MYSQLI_ASYNC);
$all_links = array($link1);
$processed = 0;
do {
$links = $errors = $reject = array();
foreach (
$all_links as $link) {
$links[] = $errors[] = $reject[] = $link;
}
if (!
mysqli_poll($links, $errors, $reject, 1)) {
continue;
}
foreach (
$links as $link) {
if (
$result = $link->reap_async_query()) {
print_r($result->fetch_row());
if (
is_object($result))
mysqli_free_result($result);
} else die(
sprintf("MySQLi Error: %s", mysqli_error($link)));
$processed++;
}
} while (
$processed < count($all_links));
?>

上面的示例将输出

Array
(
    [0] => test
)

参见

添加注释

用户贡献的注释 5 个注释

l_sanczyk at hotmail dot com
10 年前
您可以使用以下代码来执行例如 10 个同时查询

$query = "SELECT `field1`, `field2` FROM `table` WHERE `field1`='something'";

$all_links = array();
for($i=0; $i<10; $i++) {
$link = mysqli_connect("your.mysql.server.here","your@user","pa$$w0rd",DataBase_Name");
$link->query($query, MYSQLI_ASYNC);
$all_links[] = $link;
}

$processed = 0;
do {
$links = $errors = $reject = array();
foreach ($all_links as $link) {
$links[] = $errors[] = $reject[] = $link;
}
if (!mysqli_poll($links, $errors, $reject, 1)) {
continue;
}
foreach ($links as $link) {
if ($result = $link->reap_async_query()) {
print_r($result->fetch_row());
if (is_object($result))
mysqli_free_result($result);
} else die(sprintf("MySQLi Error: %s", mysqli_error($link)));
$processed++;
}
} while ($processed < count($all_links));

注意:如果您收到“警告:mysqli::query() 期望参数 2 为长整型,但给定字符串”错误,则您存在 mysqlnd 安装或配置问题。
shestero at meta dot ua
8 年前
有时不清楚连接“就绪”是什么意思。它是指查询完成,还是仅有部分记录可供读取?
是否可以使用异步(非阻塞)和非缓冲 SELECT 查询?即同时使用 MYSQLI_ASYNC|MYSQLI_USE_RESULT

我希望在我的循环中有一些类似轮询的代码,它有四种情况选项
1. 轮询等待超时,但结果集没有准备好的记录。
2. 一条或多条记录已准备就绪可以读取(但查询仍在运行)。
3. 查询已成功完成(无更多记录)。
4. 错误。

这可能吗?

据我所知,如果当前没有准备好的记录,从非缓冲查询中读取记录的操作将是阻塞的,并且没有函数可以获取有多少记录已准备就绪?
marcin dot wanat at gmail dot com
1 年前
值得注意的是,此文档中的示例将导致等待所有查询执行完毕才能获取结果。

5 年前,来自 php.net 的 bishop 发布了解决方案,允许在每个查询执行后立即获取结果。出于某种原因,它从未合并到 PHP 手册中。

https://bugs.php.net/bug.php?id=70505

mysqli_poll 的文档建议在运行轮询后迭代链接。

foreach ($links as $link) {
if ($result = $link->reap_async_query()) {
print_r($result->fetch_row());
if (is_object($result))
mysqli_free_result($result);
} else die(sprintf("MySQLi Error: %s", mysqli_error($link)));
$processed++;
}

当您有不同运行时间的查询时,这不是一个好的方法,因为 mysqli_reap_async_query() 会阻塞直到查询解析,这与异步轮询的性质相矛盾。

一种尊重不同运行时间的多个查询的方法是,对每个修改后的数组运行一个收割函数

$count = mysqli_poll($read, $error, $reject, 1);
if (0 < $count) {
array_walk($read, 'reap');
array_walk($error, 'reap');
array_walk($reject, 'reap');
}

function reap($link) {
$result = mysqli_reap_async_query($link);
if (is_object($result)) {
print_r($result->fetch_assoc()));
mysqli_free_result($result);
} else if (false !== $result) {
print_r($link);
} else {
die(mysqli_error($link));
}
}

这也处理了查询是 CRUD 且 reap_async_query 的结果不是结果对象的情况。
ekalashnikov at gmail dot com
6 年前
使用轮询检查慢查询的改进版本,
"KILL #ID" 如果 myqsli 连接的 id 与杀死它的连接相同,则不起作用,
因此您必须从 mysqli 断开连接,并使用新的连接重新连接到
杀死 #ID。
<?php
// 慢速 SQL 查询
$SelectSql = 'SELECT * FROM SLOW_QUERY';
$link = mysqli_connect('localhost','user','pass','database');
mysqli_query($SelectSql, MYSQLI_ASYNC);
$thread_id = mysqli_thread_id($link);
// 忽略用户中止,以便我们可以杀死查询
ignore_user_abort(true);
$MaxTime = 5; // 秒
$Overtime = false;
$StartTime = time();
do
{
// 轮询 MySQL
$links = $errors = $reject = array($link);
$poll = mysqli_poll($links, $errors, $reject, 0, 500000);
// 检查连接是否已中止且查询是否已杀死
if (connection_aborted()) {
$link_new = mysqli_connect('localhost','user','pass','database');
mysqli_kill($link_new, $thread_id);
$kill = mysqli_kill($link_new, $thread_id);
if (
$kill)
{
die();
}
}
$EndTime = time();
// 检查超时,如果检测到超时则杀死
if ($EndTime - $StartTime > $MaxTime)
{
$link_new = mysqli_connect('localhost','user','pass','database');
mysqli_kill($link_new, $thread_id);
$Overtime = true;
echo
'Error: Query took over '.$Overtime.'.';
}
} while (!
$poll && $Overtime == false);
?>
ekalashnikov at gmail dot com
6 年前
这是您可以使用轮询测试和终止慢速查询的方法。

<?php
// 慢速 SQL 查询
$SelectSql = 'SELECT * FROM SLOW_QUERY';
$link = mysqli_connect('localhost','user','pass','database');
mysqli_query($SelectSql, MYSQLI_ASYNC);
$thread_id = mysqli_thread_id($link);
// 忽略用户中止,以便我们可以杀死查询
ignore_user_abort(true);
$MaxTime = 5; // 秒
$Overtime = false;
$StartTime = time();
do
{
// 轮询 MySQL
$links = $errors = $reject = array($link);
$poll = mysqli_poll($links, $errors, $reject, 0, 500000);
// 检查连接是否已中止且查询是否已杀死
if (connection_aborted() && mysqli_kill($link, $thread_id)) {
die();
}
$EndTime = time();
// 检查超时,如果检测到超时则杀死
if ($EndTime - $StartTime > $MaxTime)
{
mysqli_kill($link, $thread_id);
$Overtime = true;
echo
'Error: Query took over '.$Overtime.'.';
}
} while (!
$poll && $Overtime == false);
?>
To Top