Hyperf协程下MySQL内存溢出主因是PDO默认启用缓冲查询,致全量结果集(如连表50万行)一次性加载至内存;须在prepare()前设PDO::MYSQL_ATTR_USE_BUFFERED_QUERY为false,配合手动fetch循环及及时unset大字段,低版本避免使用Db::cursor()或get()等ORM集合方法。

Hyperf协程下MySQL内存溢出,核心不是SQL本身太大,而是PDO默认开启缓冲查询,把整张结果集(比如连表后50万行)一次性加载进PHP内存。协程常驻不释放,OOM就来得又快又静。
关掉PDO缓冲查询
必须在prepare()之前设置:$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
设晚了无效。Hyperf的Db::select()、ORM的get()都走缓冲模式,表面逐行,实际早吃光内存。
手动fetch循环处理
禁用缓冲后,用while ($row = $stmt->fetch(PDO::FETCH_ASSOC))一行一行读,边处理边unset()大字段(如$row['content_blob']),避免中间变量累积。
慎用ORM的集合方法
Db::cursor()在Hyperf 3.1+才真正透传游标流式;低版本别信get()或cursor(),它们底层仍是fetchAll()。必须绕过ORM,直连PDO操作。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
连表查询要提前预估结果量
orders × order_items这类连表,行数可能翻几倍。若预估结果超5万行,优先拆成两步查:先查主表ID列表,再分批JOIN子表;或改用临时表+异步任务预计算,不压在协程里硬扛。










