日期:2026-07-11
标签:#面试 #八股 #后端 #MySQL #数据库 #场景题
一句话答案
很可能造成数据库、网络和客户端内存及资源压力,但是否一次性飙升取决于执行计划、排序临时表、驱动缓冲方式和应用是否流式消费;无论如何都不应无界查询千万行。
面试口语版
MySQL 执行全表扫描时 InnoDB 主要通过 Buffer Pool 读页,不一定把 1000 万结果全部同时放进一块结果内存,但排序、分组或临时表可能消耗大量内存并落盘。更常见的风险在客户端:很多 JDBC 驱动默认缓存完整 ResultSet,应用堆会快速增长甚至 OOM,同时长连接、长事务、网络传输和 GC 都受影响。正确方式是只查必要列、按主键游标分页或使用真正的流式读取,批量处理并及时释放;大导出放异步任务并限速。
影响层次
| 层次 | 可能问题 |
|---|---|
| MySQL | 全表扫描、Buffer Pool 污染、临时表、长事务 |
| 网络 | 巨量结果传输、带宽占满、超时 |
| JDBC | ResultSet 全量缓存或预取过大 |
| JVM | 对象膨胀、GC、OOM |
关键细节
SELECT *增加行宽、网络和对象创建,还可能破坏覆盖索引。- JDBC fetchSize 语义依驱动与版本配置而异,必须查文档并实测。
- 流式读取期间连接被长期占用,应设置超时并隔离任务。
- 读副本能隔离部分压力,但不能消除带宽和客户端风险。
面试官追问
- MySQL 会一次把全部结果放内存吗?
- JDBC 如何实现流式读取?
- 为什么长时间流式查询也有风险?
面试官追问参考答案
1. MySQL 会一次把全部结果放内存吗?
普通扫描通常边读边发送,数据页进入 Buffer Pool,不等于构建一个包含全部行的内存数组;但排序、聚合、临时表和网络缓冲会额外占内存,内存不足后可能落盘。客户端行为往往决定是否全量缓存结果。
2. JDBC 如何实现流式读取?
使用预编译语句、只读前向 ResultSet,并按具体 MySQL Connector/J 版本配置 cursor fetch/fetchSize 或流式模式,逐批处理后释放对象。配置语义随驱动版本变化,必须用真实环境验证堆占用和网络行为。
3. 为什么长时间流式查询也有风险?
它会长期占用数据库连接和网络,若处于一致性事务中还可能保留旧版本、拖长 undo 清理;慢消费者会形成背压。应按主键分批提交、设置任务超时和限速,必要时从快照或分析库导出。
学习清单
- 区分数据库、驱动和 JVM 三层内存。
- 掌握游标分页与流式读取的适用场景。