php内存溢出需先定位真实内存消耗源而非盲目调高memory_limit,应使用memory_get_usage()分析、流式读取大文件、游标分页查库、手动打断循环引用,并注意配置生效层级与常见误判因素。

直接用 $this->db->get() 加载几万行联查结果,PHP 内存必然爆掉——这不是配置问题,是数据获取方式错了。
分块查询时 get() 为什么只返回第一块?
每次调用 $this->db->get('table', $limit, $offset) 都会触发 _reset_select(),把之前加的 join()、order_by()、where() 全清空。第二轮实际执行的是裸表查询,很可能因缺失 JOIN 条件或排序失效导致结果为空或错乱。
- 必须显式控制
from():只在循环外调一次$this->db->from('tblProgram') - 所有
join()、order_by()必须在循环前完成,且不能传表名参数(避免重复 from) - 循环内只调
$this->db->limit($chunk, $offset)->get()->result_array(),不传表名 - 用主键范围分片(如
WHERE id BETWEEN ? AND ?)比 OFFSET 更稳定,尤其在高并发写入场景
导出 CSV 时如何避免内存溢出?
关键不是“怎么写文件”,而是“怎么不让整张结果集进内存”。临时表 + 主键分段读取是最兼容、最可控的方式。
- 先用原始 SQL 创建临时表:
CREATE TEMPORARY TABLE tmp_export AS SELECT ... - 从
tmp_export按id分批查:SELECT * FROM tmp_export WHERE id > ? ORDER BY id LIMIT 2000 - 每 chunk 用
fputcsv()直接写入文件流,不缓存整块数组 - 临时表生命周期绑定当前连接,不用手动清理,但需确保事务及时提交
count_all_results() 和 get() 连用报 “Not unique table/alias” 怎么办?
错误源于 count_all_results('table') 和 get('table') 都会各自调一次 from('table'),造成 SQL 中主表名重复声明。
- 统一由
from()显式指定主表,后续所有操作都不再传表名参数 -
count_all_results(false)的第二个参数设为false,表示不重置查询状态 -
get()调用时不传任何参数,复用已设置的from和join - 如果必须动态切表(如分月日志),优先用
$this->db->query()手写带表名的完整 SQL,绕过查询构建器的状态干扰
真正难的不是写对一行代码,而是在分块、临时表、主键分片、UNION 跨表这些方案之间,选一个和你现有 SQL 复杂度、DB 权限、运维习惯匹配的组合——比如线上库没 CREATE 权限,就别碰临时表;要是 JOIN 里有子查询,OFFSET 分页基本不可靠,得切到游标模式。











