我有如下粗略的代码(完整代码146行,其中90行是字符串解析,需要的可以补充):
ini_set('memory_limit', '7G');
$db = new PDO("mysql:host=".$dbhost.";dbname=".$dbname, $dbuser, $dbpass, array(PDO::ATTR_PERSISTENT => true));
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$db_ub = new PDO("mysql:host=".$dbhost.";dbname=".$dbname, $dbuser, $dbpass, array(PDO::ATTR_PERSISTENT => true));
$db_ub->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$stmt = $db->prepare('select columns from stats where timestamp between ? and ?');
$stmt->execute(array('2020-04-25', '2020-05-25'));
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo memory_get_usage() .PHP_EOL;
echo $row['id'] . PHP_EOL;
$stmt2 = $db_ub->prepare('select somedata from users limit 1');
$stmt2->execute();
$row2 = $stmt2->fetch(PDO::FETCH_ASSOC);
$type = !empty($row2['somedate']) ? 5 : 4;
$result = $db_ub->prepare('insert ignore into newtable (old, type) values (?, ?)');
$result->execute(array($row['id'], $type));
}
在$stmt->execute(array('2020-04-25', '2020-05-25'));我的内存消耗期间.34GB(用于ps aux | grep 'php ' | awk '{$5=int(100 * $5/1024/1024)/100"GB";}{ print;}'监视消耗select和show full processlistSQL 端验证)。一旦脚本进入,while它就会跳转到 +5 GB。
测试setattribute
var_dump($db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false));
好像已经生效了:
bool(true)
但是当我切换缓冲或无缓冲时,行为不会改变。
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false)
和
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true)
使用echo $db->getAttribute(constant('PDO::MYSQL_ATTR_USE_BUFFERED_QUERY'));还显示设置更改。
将设置移动到语句而不是https://www.php.net/manual/en/ref.pdo-mysql.php建议的连接也没有用。
$stmt = $db->prepare('select columns from stats where timestamp between ? and ?', array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false));
我也试过将缓冲区设置移动到连接而没有影响:
$db = new PDO("mysql:host=".$dbhost.";dbname=".$dbname, $dbuser, $dbpass, array(PDO::ATTR_PERSISTENT => true, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false));
POPMUISE
米脂
慕后森