Подтвердить что ты не робот

Неожиданно поражает ограничение памяти PHP с помощью одного запроса PDO?

У меня действительно простой запрос, который выглядит примерно так:

$result = $pdo->query('SELECT * FROM my_table');

foreach($result as $r) {
    // do some stuff
}

Но когда я запускаю это, я получаю следующую ошибку:

Неустранимая ошибка: допустимый размер памяти 134217728 байт исчерпан (попытался выделить 32 байта) в /path/to/myfile.php в строке 15

"Строка 15" - это строка $pdo->query.

Если я поместил die() после запроса, я все равно получаю ту же ошибку.

Я думал, что это должно было случиться только во время одной строки; почему он использует столько памяти?

4b9b3361

Ответ 1

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

Ding ding ding!

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

Но, как и все в PHP, там есть. Как отмечено на странице буферизации:

При использовании libmysql в качестве библиотеки Предел памяти PHP не будет считать память, используемую для наборов результатов, если данные не будут загружены в переменные PHP. С mysqlnd учетная запись будет включать полный набор результатов.

Вы используете PHP 5.3, а это означает, что есть хороший шанс, что вы используете mysqlnd.

Здесь вы захотите отключить буферизованные запросы. Это было сделано по-разному в каждом интерфейсе PHP для MySQL:

  • Для PDO вам нужно установить атрибут PDO::MYSQL_ATTR_USE_BUFFERED_QUERY в false.
  • Для mysqli вам необходимо передать константу MYSQLI_USE_RESULT в метод query.
  • Для mysql вам нужно вызвать mysql_unbuffered_query вместо mysql_query.

Подробные сведения и примеры приведены на странице.

Большой небуферизованный запрос запроса!

Вы должны правильно закрыть дескриптор оператора и освободить набор результатов перед выдачей другого запроса:

  • В PDO это означает вызов closeCursor в дескрипторе инструкции.
  • В mysqli это означает вызов free_result в дескрипторе инструкции или free в дескрипторе результата, в зависимости от того, с чем вы работаете.
  • В mysql это означает вызов mysql_free_result

Невыполнение этого условия приведет к ошибке.