|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2015-09-15 15:15 UTC] bishop@php.net
Description: ------------ When mysqli_poll is given a single link in its read array, and the async query on that link runs longer than the timeout, the timeout expires and poll returns (correctly) that nothing is ready to read. However, in the same scenario when there are multiple links to read, mysqli_poll ignores the timeout and returns only when the longest running query resolves. The man page is light on this function, so maybe I am misunderstanding how timeout should work. Also, there's further discussion at this SO post: http://stackoverflow.com/a/32576278/2908724 Test script: --------------- $link0 = mysqli_connect(...); $link1 = mysqli_connect(...); $link2 = mysqli_connect(...); $sql0 = 'SELECT SLEEP(2) AS wait, 1 AS num'; $sql1 = 'SELECT foo FROM'; $sql2 = 'SELECT 2 AS num'; mysqli_query($link0, $sql0, MYSQLI_ASYNC); mysqli_query($link1, $sql1, MYSQLI_ASYNC); mysqli_query($link2, $sql2, MYSQLI_ASYNC); $links = array ($link0, $link1, $link2); $begin = microtime(true); $i = 0; do { printf("start i=%d @ T+%.f\n", $i, (microtime(true)-$begin)); $read = $error = $reject = $links; $count = mysqli_poll($read, $error, $reject, 1, 500000); if (0 < $count) { foreach ($links as $j => $link) { $result = mysqli_reap_async_query($link); if (is_object($result)) { printf("link #%d, row=%s\n", $j, json_encode($result->fetch_assoc())); mysqli_free_result($result); } else if (false !== $result) { printf("link #%d, output=%s\n", $j, $link); } else { printf("link #%d, error=%s\n", $j, mysqli_error($link)); } } } printf( "finish i=%d, count(read, error, reject)=(%d, %d, %d) @ T+%f\n\n", $i++, count($read), count($error), count($reject), (microtime(true)-$begin) ); } while (count($links) !== count($read) + count($error) + count($reject)); Expected result: ---------------- start i=0 @ T+0.000000 link #0, row=null link #1, error=You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 link #2, row={"num":"2"} finish i=0, count(read, error, reject)=(1, 1, 0) @ T+1.500000 start i=1 @ T+1.500000 link #0, row={"wait":"0",a"num":"2"} link #1, row=null link #2, row=null finish i=0, count(read, error, reject)=(1, 0, 2) @ T+2.000000 Actual result: -------------- start i=0 @ T+0.000002 link #0, row={"wait":"0","num":"1"} link #1, error=You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 link #2, row={"num":"2"} finish i=0, count(read, error, reject)=(1, 0, 0) @ T+2.001756 start i=1 @ T+2.001827 finish i=1, count(read, error, reject)=(0, 0, 3) @ T+3.503024 PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 28 12:00:01 2025 UTC |
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.