- Обзор
- Асинхронные запросы
- Подготовленные выражения
- Хранимые процедуры
- Множественные запросы
Асинхронный, неблокирующий ввод-вывод это старая идея. Вот и в PHP расширении mysqli присутствует возможность асинхронных запросов. Эта возможность доступна только при использовании библиотеки mysqlnd (в противовес libmysql).
В обычной схеме, после отправки запроса к БД PHP-скрипт заблокирован до получения ответа (в самом распространённом варианте: до получения всех записей соответствующих запросу). При использовании асинхронности скрипт продолжает работу сразу же после отправки запроса, а затем уже можно производить опрос mysqli-объектов с целью получения ответов.
По-моему применение асинхронных запросов специфично в условиях больших проектов, где используется распределение БД или, возможно, в цикличных системах, где необходима постоянная «отзывчивость» программы. В реальной жизни с такими условиями я ещё не сталкивался, но функциональность есть, и я её рассмотрю.
MySQL протокол клиент-сервер не имеет встроенной поддержки асинхронности, поэтому для её реализации в PHP необходимо отдельное соединение (объект mysqli) на каждый запрос.
Для отправка асинхронного запроса в метод mysqli::query() добавляется второй параметр «MYSQLI_ASYNC»:
$mysqli = new mysqli('host', 'user', 'pass', 'database'); $mysqli->query('...', MYSQLI_ASYNC);
При опросе соединения на предмет получения результата предлагается использовать статический метод mysqli::poll(). Но в PHP 5.3.3 (той, что у меня сейчас установлена) этот метод почему-то недоступен, поэтому я использую процедурный вариант, т.е. mysqli_poll():
mysqli_poll($read, $write, $error, 1);
Добавим проверку ошибок, вывод результатов и получим рабочий пример:
$mysqli = new mysqli('host', 'user', 'pass', 'database'); $mysqli->query('SELECT * FROM `test`', MYSQLI_ASYNC); $all_links = array($mysqli); $processed = 0; do { $read = $write = $error = array(); foreach ($all_links as $link) { $read[] = $write[] = $error[] = $link; } if (!mysqli_poll($read, $write, $error, 1)) { if (count($error)) foreach ($error as $link) { echo $link->error . '<br />'; $processed++; } } foreach ($read as $link) { if ($result = $link->reap_async_query()) { if (is_object($result)) // for SELECT { print_r($result->fetch_row()); $result->free(); } else { // for INSERT / UPDATE / DELETE print_r($link); } $processed++; } } } while ($processed < count($all_links)); $mysqli->close();
Описанная выше функциональность плохо документирована, поэтому следующие ссылки могут пригодиться:
- PHP: parallel, background, asynchronous fetch
- PHP: How mysqlnd async queries help you with sharding!
Комментариев нет:
Отправить комментарий