怎么从内存区域视角剖析单次大 SQL 查询未加限制误回传百万记录引发的崩溃

冷漠man

冷漠man

2026-06-03

874人浏览

原创

本质是客户端缓冲区率先溢出,驱动默认缓存整结果集致jvm堆或进程内存超限;继而服务端sort/join_buffer超限触发磁盘spill;长连接堆积耗尽连接池;最终系统级oom killer介入杀进程。

怎么从内存区域视角剖析单次大 sql 查询未加限制误回传百万记录引发的崩溃

单次大 SQL 查询未加限制导致返回百万级记录,本质是内存资源被突发性、非预期地耗尽。从内存区域视角看,崩溃不是“突然发生”,而是多个内存区域在查询执行链路上相继承压、突破阈值后的连锁反应。

客户端缓冲区率先溢出

大多数数据库驱动(如 MySQL 的 mysqlclient、PostgreSQL 的 libpq)默认启用结果集缓存,将整条查询结果一次性拉取到本地内存中。当服务端返回百万行、每行平均 2KB,仅数据体就超 2GB——远超客户端进程默认堆上限(如 Python 的 sys.getsizeof() 不体现实际分配,但 malloc 分配会失败)。

  • Java 应用常见报错:java.lang.OutOfMemoryError: Java heap space
  • Python 常见表现:进程被 OS OOM Killer 杀死,日志出现 Killed process xxx (python) total-vm:XXXXkB, anon-rss:XXXXkB
  • 规避方式:启用流式读取(如 MySQL 的 cursor(buffered=False),PostgreSQL 的 named cursor + fetchmany()

服务端查询工作内存超限

数据库自身也有关键内存区域参与该查询:MySQL 的 sort_buffer_sizejoin_buffer_size,PostgreSQL 的 work_mem。若查询含 ORDER BYGROUP BY 或多表 JOIN,这些区域会按需放大——尤其当优化器误判行数(百万行被估为千行),分配的内存远小于实际所需,触发磁盘临时文件(spill to disk),但若磁盘 I/O 拥塞或临时空间不足,查询直接中止并可能拖垮连接池。

豆绘AI
豆绘AI

豆绘AI是国内领先的AI绘图与设计平台,支持照片、设计、绘画的一键生成。

下载
  • MySQL 查看当前会话内存使用:SELECT * FROM performance_schema.memory_summary_by_thread_by_event_name WHERE event_name LIKE 'memory/sql/%' AND thread_id = CONNECTION_ID();
  • PostgreSQL 监控:EXPLAIN (ANALYZE, BUFFERS) 可看到 Temp filesBuffers 实际用量
  • 建议:对非管理类接口,强制设置会话级限制,如 SET SESSION work_mem = '4MB';

连接与线程栈持续占位,引发雪崩

即使查询最终失败,其占用的连接不会立刻释放:MySQL 线程处于 Sending dataCopying to tmp table 状态时,连接仍计入 max_connections;PostgreSQL 后端进程在清理阶段也可能卡住。大量此类长连接堆积,迅速吃光连接池,新请求排队等待,进而拖慢整个实例响应,监控显示 Threads_connected 持续高位、QPS 断崖下跌

  • MySQL 快速识别问题连接:SHOW PROCESSLIST; 找出 Time 值极大且 State 异常的线程
  • 主动终止:KILL [connection_id];
  • 根本防护:应用层设置查询超时(如 JDBC 的 socketTimeoutqueryTimeout),数据库层配置 wait_timeout / idle_in_transaction_session_timeout

系统级内存压力触发全局回收

当数据库进程 RSS 内存持续飙升(如 mysqld 占用 16GB+),OS 内核的 kswapd 频繁扫描页框,pgmajfault 上升,其他进程(如监控 agent、日志收集器)也因内存竞争变慢。极端情况下,内核 OOM Killer 根据 oom_score_adj 选择杀掉高内存进程——不一定是数据库本身,可能是同机器的 Redis 或 Nginx,造成多服务连环故障。

  • 检查历史 OOM:dmesg -T | grep -i "killed process"
  • 限制数据库内存上限:MySQL 通过 cgroup v2 或容器 memory limit;PostgreSQL 推荐配合 shared_buffers + effective_cache_size 合理规划,避免过度预留
  • 上线前压测必须包含“无 LIMIT 的全表扫描”场景,观测各层内存增长曲线
PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

2473

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

449

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

614

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3970

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

1346

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

3562

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

3515

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

642

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

526

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.4万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 131.8万人学习