mysql内存过高需区分合理缓存与异常占用:重点调优 innodb_buffer_pool_size(60%–80% 物理内存)、tmp_table_size/max_heap_table_size(16–64MB)、线程 级参数及 max_connections;通过 sys/performance_schema 查内存分布;结合 PROCEsslIST、EXPLai N 定位低效 SQL;检查大表、冗余索引及存储过程。

MySQL内存占用 过高,核心在于区分“合理缓存”和“异常占用”。InnoDB 缓冲池(innodb_buffer_pool_size)占大头是正常的,但若实际使用远超配置值、或内存持续增长不释放,就需系统排查。
查关键内存参数是否失当
重点检查以下几项是否与服务器物理内存不匹配:
- innodb_buffer_pool_size:应设为物理内存的 60%–80%,例如 64GB 内存建议设 40–52GB。设太高会挤占系统和其他进程空间;设太低则频繁刷盘,反而拖慢性能。
- tmp_table_size 和 max_heap_table_size:两者需一致,建议 16–64MB。过大会让内部临时表长期驻留内存,尤其在 GROUP BY、ORDER BY 未走索引时。
- sort_buffer_size、join_buffer_size等线程级参数:默认值(256KB–4MB)通常足够。盲目调大(如设到 32MB)会导致每个活跃连接多占几十 MB,连接数一多就雪崩。
- max_connections:设 2000 但实际峰值仅 300,MySQL 仍会为每个连接预分配线程内存,造成浪费。应按真实 并发 压测结果设置,并配合应用端连接池控制。
看内存实际用在哪
别只看 top 里mysql d 占了多少,要进 MySQL 查真实分布:
- 执行 red”>select SUM(CAST(REPLACE(current_alloc,’MiB’,”) AS DECIMAL(10,2))) FROM sys.memory_global_by_current_bytes WHERE current_alloc LIKE ‘%MiB%’; —— 看全局内存总用量(单位 MB)。
- 执行 SELECT event_name, sys.format_bytes(CURRENT_NUMBER_OF_BYTES_USED) FROM performance_schema.memory_summary_global_by_event_name ORDER BY CURRENT_NUMBER_OF_BYTES_USED DESC LIMIT 10; —— 找出前 10 大内存消耗模块,比如
memory/innodb/buf_buf_pool(正常)、memory/temptable/physical_ram(可能 SQL 有缺陷)、memory/group_rpl/Gcs_xcom::xcom_cache(主从复制积压)。 - 执行 SELECT user, event_name, ROUND(current_number_of_bytes_used/1024/1024,2) AS mb_used FROM performance_schema.memory_summary_by_account_by_event_name WHERE host != ‘localhost’ ORDER BY mb_used DESC LIMIT 5; —— 定位高内存消耗账号,结合其 SQL 分析问题根源。
盯连接与查询行为
内存不释放常源于长连接 + 低效 SQL,而非配置本身:
- 运行 SHOW FULL PROCESSLIST;,重点关注
State为Copying to tmp table、Sorting result、Sending data且Time大于 60 秒的线程——这类查询大概率没走索引或数据量过大。 - 对可疑 SQL 执行 EXPLAIN,确认是否全表扫描、是否用了临时表、是否需要文件排序(
Extra列含using filesort或Using temporary)。 - 检查是否存在大量 Sleep 连接未断开(如应用未正确 close)。可用 SHOW STATUS LIKE ‘Threads_connected’; 对比 max_connections,若长期接近上限,说明连接泄漏。
查 对象 与数据规模是否失控
有些问题藏在 数据库 结构里:
- 执行 SELECT table_schema, table_name, round(((data_length + index_length)/1024/1024),2) AS size_mb FROM information_schema.TABLES ORDER BY size_mb DESC LIMIT 10; —— 找出 TOP10 大表。单表超 50GB 且无分区,易导致大查询内存爆增。
- 检查冗余索引:SELECT * FROM sys.schema_redundant_indexes;。多余索引不仅占磁盘,还会在写入和部分查询中增加内存开销。
- 查看存储过程 / 函数数量:SELECT COUNT(*) FROM information_schema.ROUTINES WHERE routine_schema NOT IN (‘mysql’,’sys’,’information_schema’,’performance_schema’);。大量复杂逻辑 封装 在服务端,可能隐式申请大量内存且难追踪。