• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • mysqli::poll()

    (PHP 5 >= 5.3.0, PHP 7)

    轮询连接

    说明

    面向对象风格
    publicstaticmysqli::poll(array &$read,array &$error,array &$reject,int $sec[,int $usec= 0]): int
    过程化风格
    mysqli_poll(array &$read,array &$error,array &$reject,int $sec[,int $usec= 0]): int

    轮询连接。仅可用于mysqlnd。此方法是static的。

    参数

    $read

    要检测是否存在可以读取的结果集的连接的数组。

    $error

    发生错误的,例如:SQL 语句执行失败或者已经断开的连接的数组。

    $reject

    没有可以读取的结果集的连接的数组。

    $sec

    秒为单位的最大等待时间,不可以为负数。

    $usec

    微秒为单位的最大等待时间,不可以为负数。

    返回值

    成功执行则返回存在可以读取结果集的连接数量,否则FALSE

    范例

    Example #1 A 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
    )
    

    参见

    • mysqli_query() 对数据库执行一次查询
    • mysqli_reap_async_query() 获取异步查询的结果
    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 ?
    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.
    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);
    ?>
    
    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);
    ?>
    

    上篇:mysqli::ping()

    下篇:mysqli::prepare()