|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2018-12-17 09:16 UTC] sjon at hortensius dot net
Description:
------------
commit f1f1f6 broke unbuffered queries in mysqlnd; there is a memory leak causing php to run out of memory
Test script:
---------------
<?php
ini_set('memory_limit', '8M');
$pdo = new PDO('mysql:host=*;dbname=*', '*', '*');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$result = $pdo->query("SELECT * FROM large_table");
foreach ($result as $i => $row)
if ($i % 10000 === 0)
printf("%10s %10s\n", $i, memory_get_usage());
Expected result:
----------------
reasonable constant memory usage, eg:
0 427648
10000 427936
20000 427968
30000 427968
40000 427936
Actual result:
--------------
0 427296
10000 2000288
20000 3622336
30000 5260736
40000 6915488
Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 16384 bytes) in /php on line 10
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 05:00:02 2025 UTC |
Test script including (slow) table generation: <?php ini_set('memory_limit', '8M'); $pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'php-test', 'password'); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); $pdo->exec("DROP TABLE IF EXISTS large_table"); $pdo->exec("CREATE TABLE large_table (id int)"); for ($j = 0; $j < 100; $j++) { $query = "INSERT INTO large_table (id) VALUES "; for ($i = 0; $i < 10000; $i++) { $query .= "($i), "; } $query .= "($i)"; $pdo->exec($query); } $result = $pdo->query("SELECT * FROM large_table"); foreach ($result as $i => $row) if ($i % 10000 === 0) printf("%10s %10s\n", $i, memory_get_usage()); I'm also getting a Warning: Packets out of order. Expected 231 received 48. Packet size=3422212 in Unknown on line 0 after the memory limit error.Still present in 7.3.3 Some details of test run: --- 1. Versions #/opt/php71/bin/php -v PHP 7.1.27 (cli) (built: Mar 18 2019 13:00:22) ( ZTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies # /opt/php72/bin/php -v PHP 7.2.16 (cli) (built: Mar 18 2019 13:03:57) ( ZTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies # /opt/php73/bin/php -v PHP 7.3.3 (cli) (built: Mar 18 2019 13:07:58) ( ZTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.3, Copyright (c) 1998-2018 Zend Technologies --- 2. Top data for ~10 sec of script run 7.1: 112241 root 20 0 307892 13932 8396 R 100.0 0.2 0:11.82 /opt/php71/bin/php ./test.php 7.2: 111796 root 20 0 310480 14228 8460 R 99.7 0.2 0:10.41 /opt/php72/bin/php ./test.php 7.3: 110517 root 20 0 1148804 848480 8716 R 99.7 10.4 0:10.37 /opt/php73/bin/php ./test.php You can easily see RES size growing from stable 14M on PHP 7.1/7.2 to 840M+ on PHP 7.3. The script fails with out of memory error eventually (Allowed memory size of 1073741824 bytes exhausted (tried to allocate 16384 bytes) in /config/scripts/test.php on line 10) --- 3. Script excerpt (it's ultimately simple, but the query returns 11+ million rows) #!/opt/php73/bin/php <?php error_reporting(E_ALL); ini_set('display_errors', 1); ini_set('memory_limit', '1G'); $db = new MySQLi('<server>', '<login>', '<password>', 'radius'); $res = $db->query('SELECT `AcctSessionId` AS `sid`, `AcctUniqueId` AS `uid` FROM `radacct` ORDER BY `AcctSessionId`, `AcctUniqueId`', MYSQLI_USE_RESULT); while (is_array($row = $res->fetch_assoc())); $res->free(); ---