mysqli::poll

mysqli_poll

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

mysqli::poll -- mysqli_pollSondagem de conexões

Descrição

Estilo orientado a objetos

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

Estilo procedural

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

Faz sondagem de conexões. Este método pode ser usado como static.

Nota:

Disponível apenas com o mysqlnd.

Parâmetros

read

Lista de conexões a verificar por resultados marcantes que possam ser lidos.

error

Lista de conexões nas quais um erro ocorreu, por exemplo, falha na consulta ou conexão perdida.

reject

Lista de conexões rejeitadas porque nenhuma consulta assícrona foi executada para que a função pudesse sondar os resultados.

seconds

Número máximo de segundos a esperar, deve ser não negativo.

microseconds

Número máximo de microssegundos a esperar, deve ser não negativo.

Valor Retornado

Retorna o número de conexões prontas em caso de sucesso, false caso contrário.

Erros/Exceções

Uma exceção ValueError é lançada quando nem o parâmetro read nem o parâmetro error são passados.

Registro de Alterações

Versão Descrição
8.3.0 Agora lançã uma exceção ValueError quando nem o parâmetro read nem o parâmetro error são passados.

Exemplos

Exemplo #1 Um exemplo de 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));
?>

O exemplo acima produzirá:

Array
(
    [0] => test
)

Veja Também

add a note add a note

User Contributed Notes 5 notes

up
7
l_sanczyk at hotmail dot com
10 years ago
You can use the following code to execute, for example, 10 simultaneous queries:

$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));

NOTE: If you get a "Warning: mysqli::query() expects parameter 2 to be long, string given" you have a mysqlnd installation or configuration issue.
up
5
shestero at meta dot ua
8 years ago
Sometime it's not clear what does it mean as connection is "ready" . Does it mean the query completed or just some records ready to read?
Is it possible to use asynchronous (unblocking) and unbuffered SELECT-query? I.e. with both MYSQLI_ASYNC|MYSQLI_USE_RESULT

I want some poll-like code inside my loop that has four case-options:
1. Poll wait time-out is over but no records of result set is ready.
2. One or more records are ready to read (but the query still running).
3. Query is successfully over (completed; no more records).
4. Error.

Is it possible?

As I understood the operation of reading a record from unbuffered query is blocking if there are no ready records at the moment, and there is no functions to get out how much records are ready ?
up
1
marcin dot wanat at gmail dot com
1 year ago
It is worth to note that example from this docs will results in waiting for all queries to be executed before you can reap your results.

5 years ago bishop from php.net has posted solution that allow to fetch results of each query immediately after executed. For some reason this has never been merged to php manual.

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

The documentation for mysqli_poll suggests iterating through the links after running the 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++;
    }

This is not a good way to go about it when you have queries of different run-times, because mysqli_reap_async_query() blocks until the query resolves, which is contrary to the nature of the async poll.

An approach that respects multiple queries of different run times is to run a reaping function over each of the modified arrays:

    $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));
    }
}

This also handles the case where the query is a CRUD and the result of reap_async_query isn't a result object.
up
0
ekalashnikov at gmail dot com
7 years ago
Improved version of using polling to check for slow query,
"KILL #ID" does not work if id of the myqsli link is the same as the one that kills it,
so you have to disconnect from mysqli and connect again with new link to
kill the #ID.
<?php
// Slow SQL Query
     
$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 so we can kill the query
     
ignore_user_abort(true);
     
$MaxTime = 5; // seconds
     
$Overtime = false;
     
$StartTime = time();
      do
      {
         
// Poll MySQL
       
$links = $errors = $reject = array($link);
       
$poll = mysqli_poll($links, $errors, $reject, 0, 500000);
        
// Check if the connection is aborted and the query was killed
       
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();
       
// Check overtime, kill if detected overtime
       
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);
?>
up
0
ekalashnikov at gmail dot com
7 years ago
This is how you can test and terminate slow query with polling.

<?php
// Slow SQL Query
     
$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 so we can kill the query
     
ignore_user_abort(true);
     
$MaxTime = 5; // seconds
     
$Overtime = false;
     
$StartTime = time();
      do
      {
         
// Poll MySQL
       
$links = $errors = $reject = array($link);
       
$poll = mysqli_poll($links, $errors, $reject, 0, 500000);
        
// Check if the connection is aborted and the query was killed
       
if (connection_aborted() && mysqli_kill($link, $thread_id)) {
            die();
        }
       
$EndTime = time();
       
// Check overtime, kill if detected overtime
       
if ($EndTime - $StartTime > $MaxTime)
        {
         
mysqli_kill($link, $thread_id);
         
$Overtime = true;
          echo
'Error: Query took over '.$Overtime.'.';
        }
      } while (!
$poll && $Overtime == false);
?>
To Top