PHP асинхронный MySQL-запрос

Мое приложение сначала запрашивает 2 больших набора данных, затем выполняет некоторую работу с первым набором данных и «использует» его во втором.

Если возможно, я бы хотел, чтобы вместо этого он запрашивал только первый набор синхронно, а второй — асинхронно, выполнял работу с первым набором, а затем ждал завершения запроса второго набора, если он еще не завершен, и, наконец, использовал первый набор. набор данных о нем.

Это возможно как-то?

7

Решение

Возможно.

$mysqli->query($long_running_sql, MYSQLI_ASYNC);

echo 'run other stuff';

$result = $mysqli->reap_async_query(); //gives result (and blocks script if query is not done)
$resultArray = $result->fetch_assoc();

Или вы можете использовать mysqli_poll, если вы не хотите иметь блокирующий вызов

http://php.net/manual/en/mysqli.poll.php

16

Другие решения

MySQL требует, чтобы внутри одного соединения запрос был полностью обработан до запуска следующего запроса. Тот включает в себя получение все Результаты.

Однако возможно:

  • получать результаты один за другим, а не все сразу
  • запустить несколько запросов, создав несколько соединений

По умолчанию PHP будет ждать до все результаты доступны и затем внутренне (в драйвере mysql) извлекают все результаты сразу. Это правда даже при использовании, например PDOStatement::fetch() импортировать их в свой код по одной строке за раз. При использовании PDO это можно предотвратить с помощью настройки атрибута \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY в false, Это полезно для:

Имейте в виду, что часто скорость ограничена системой хранения с характеристиками, которые означают, что общее время обработки для двух запросов больше при их одновременном выполнении, чем при выполнении их один за другим.

Пример (который может быть полностью выполнен в MySQL, но для демонстрации концепции …):

$dbConnectionOne = new \PDO('mysql:hostname=localhost;dbname=test', 'user', 'pass');
$dbConnectionOne->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

$dbConnectionTwo = new \PDO('mysql:hostname=localhost;dbname=test', 'user', 'pass');
$dbConnectionTwo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$dbConnectionTwo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

$synchStmt = $dbConnectionOne->prepare('SELECT id, name, factor FROM measurementConfiguration');
$synchStmt->execute();

$asynchStmt = $dbConnectionTwo->prepare('SELECT measurementConfiguration_id, timestamp, value FROM hugeMeasurementsTable');
$asynchStmt->execute();

$measurementConfiguration = array();
foreach ($synchStmt->fetchAll() as $synchStmtRow) {
$measurementConfiguration[$synchStmtRow['id']] = array(
'name' => $synchStmtRow['name'],
'factor' => $synchStmtRow['factor']
);
}

while (($asynchStmtRow = $asynchStmt->fetch()) !== false) {
$currentMeasurementConfiguration = $measurementConfiguration[$asynchStmtRow['measurementConfiguration_id']];
echo 'Measurement of sensor ' . $currentMeasurementConfiguration['name'] . ' at ' . $asynchStmtRow['timestamp'] . ' was ' . ($asynchStmtRow['value'] * $currentMeasurementConfiguration['factor']) . PHP_EOL;
}
10