PHP memory_get_usage返回负值求助:大表查询内存测量异常
问题原因:内存溢出触发整数溢出
你的q1查询返回1100万+行数据,fetchAll()会把所有结果一次性加载到PHP内存中。如果你的PHP是32位版本,memory_get_usage()返回的是有符号32位整数,最大值约为2147MB(2^31-1)。当内存占用超过这个阈值时,整数会溢出,数值直接翻转成负数——这就是$m2出现负值的核心原因。
而q2因为做了group by cid,结果集行数大幅减少(最多为1100万行,最少约360万行),内存占用未突破32位整数上限,所以能正常显示数值。
正确测量内存的方案
切换到64位PHP环境
64位PHP的整数类型支持极大的数值范围(最大值约9e18),可以准确记录超过2GB的内存占用,从根源上避免整数溢出导致的负值问题。避免一次性加载全量结果
放弃fetchAll()一次性加载所有数据的做法,改用逐行或分批获取的方式处理结果,既能大幅降低内存占用,也能更精准地测量单批数据的内存消耗:function test($query){ $m1 = memory_get_usage(); $q = DB->query($query); $rowCount = 0; while ($row = $q->fetch()) { $rowCount++; // 在这里处理单条数据逻辑 } $m2 = memory_get_usage(); return [$m2, $m1, $rowCount]; }使用峰值内存测量函数
改用memory_get_peak_usage()替代memory_get_usage(),它返回脚本执行过程中使用的内存峰值,能更准确反映查询和结果处理过程中实际占用的最大内存,避免因测量时机偏差导致的结果不准:function test($query){ $m1 = memory_get_peak_usage(); $q = DB->query($query); $r = $q->fetchAll(); $m2 = memory_get_peak_usage(); return [$m2, $m1]; }谨慎调整PHP内存限制
如果必须一次性加载全量数据,可以临时调大php.ini中的memory_limit(例如设置为4G),但这只是应急方案——大结果集一次性加载始终是低效且易引发内存溢出的做法,不建议长期使用。
内容的提问来源于stack exchange,提问作者PM_KLS
相关产品推荐
相关产品推荐

