PHP теряет курсор mongoDB, несмотря на длительные таймауты

88
9

Я запускаю длинный запрос mongoDB следующим образом:


foreach($xyz->find(...)->timeout(24 * 60 * 60 * 1000)->maxTimeMS(24 * 60 * 60 * 1000) as $document) {
...
}

Но, несмотря на те 24-часовые тайм-ауты для клиента и сервера, script выйдет с помощью MongoCursorException через несколько минут:


localhost: 27017: не удалось найти курсор над набором xyz



Я на PHP 5.4 с драйвером v7.6.10 mongoDB. БД является mongoDB 3.0.4. PHP будет подключаться к экземпляру mongos, коллекция xyz будет опечатана.


Любая идея, что может вызвать это исключение?

спросил(а) 2021-01-25T20:11:30+03:00 4 месяца, 2 недели назад
1
Решение
63

Похоже, что есть больше тайм-аутов, которые не все поддерживаются PHP (пока). Один из них maxIdleTimeMS:


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



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

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


$cursor->batchSize(-20)

В этом примере не более 20 документов передаются между сервером и клиентом для каждой партии. Это уменьшает вероятность того, что соединение простаивает слишком долго. Конечно, точное значение зависит от загрузки вашей базы данных, как долго вам нужно обрабатывать каждый документ и т.д.

ответил(а) 2021-01-25T20:11:30+03:00 4 месяца, 2 недели назад
63

Я должен сказать, что у меня есть аналогичный опыт, у меня есть коллекция, которую я просматриваю через


$items  = $col -> find(['data' => 'OK']);
$items->timeout(-1);
$items->maxTimeMS(3600*1000);

но после прохождения через


foreach($items as $item)
{
///... processing
}

примерно через 12 - 15 минут, я получаю ту же ошибку


could not find cursor over collection

В коллекции содержится около 150000 записей, и интересным фактом является то, что ошибка всегда появляется после обработки 123479 записей независимо от содержимого 123480-й записи и независимо от времени, затраченного на обработку соответствующих записей (время необходимые для обработки записи, могут варьироваться в зависимости от содержимого).


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

ответил(а) 2021-01-25T20:11:30+03:00 4 месяца, 2 недели назад
45

У меня была такая же проблема. Я пробовал с последней версией двух драйверов,


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


Решение для меня использовало метод toArray MongoDB\Driver\Cursor (Драйвер mongodb)


Это возвращает массив со всеми документами. У меня есть пакет, который работает с более чем 100k документами без проблем.

ответил(а) 2021-01-25T20:11:30+03:00 4 месяца, 2 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема