新闻详情

新闻详情

首页 / 资讯中心 / 详情

MySQL内存占用高?从缓冲池到连接线程的排查与优化实战

发布时间:2026/9/26 12:28:25来源:尧图网络
MySQL内存占用高?从缓冲池到连接线程的排查与优化实战
1. 故障现象MySQL 内存占用到底该怎么看先说个真实场景。去年我接手一台线上服务器配置是 16G 内存跑着 MySQL 8.0 和几个 Java 应用。某天监控报警说内存使用率飙到 95% 以上。我登录服务器一看free -h显示 used 接近 15G但细细一算Java 应用加起来也就占了 6G 左右剩下的内存几乎全被 mysqld 吃掉了。很多朋友一遇到 MySQL 内存占用高第一反应是“是不是内存泄漏了”然后急着重启数据库。其实这个结论下得太早。MySQL 内存占用高有相当一部分是正常现象特别是 InnoDB 引擎的缓冲池和操作系统的 Page Cache 机制会导致内存看着很高但实际并不影响性能。真正需要警惕的是那部分“只涨不降、涨到系统 OOM”的内存。排查之前先把口径统一了。Linux 下看内存别只看free -m里的 used 列要看这几项指标含义说明total物理内存总量服务器实际内存used已使用内存包含 cache/bufferfree完全空闲的内存不含任何缓存available可分配给新进程的内存包含可回收的 cachebuff/cache文件缓存可回收不用太紧张重点记住一句话free命令里的 used 包含了 buff/cache这部分内存是 Linux 的文件页缓存MySQL 读了磁盘数据后操作系统会把这些数据留在内存里下次读取直接命中缓存速度飞快。如果 MySQL 内存高主要高在 buff/cache 上这其实是好事根本不叫问题。真正需要排查的是RES常驻内存这一列也就是 mysqld 进程真正占用的物理内存。所以第一步不是急着优化而是先精确定位到底是 mysqld 的哪个内存区域吃掉了内存是 InnoDB Buffer Pool还是连接线程还是排序缓冲还是其他临时结构。定位错了方向后面所有的优化都白做。2. 先分清正常占用 vs 异常占用2.1 InnoDB Buffer Pool 是内存大户但这不算故障InnoDB Buffer Pool以下简称 BP是 MySQL 内存占比最大的部分默认配置下可能占物理内存的 60% 到 80%。它缓存的是表数据页和索引页相当于把磁盘上的热点数据预加载到内存里减少磁盘 IO。举个生活化的例子BP 就像你家楼下的便利店老板会把卖得最好的几款饮料放在冰柜最显眼的位置。你每次来买不用让店员去仓库翻直接拿起就走。如果冰柜太小每次都要去仓库取那顾客体验就很差。MySQL 的 BP 就是这个冰柜大小决定了一半以上的性能。既然 BP 是“缓存”它占内存就是合理的。但问题在于如果innodb_buffer_pool_size配得太大超过了物理内存减去系统和其他应用所需的总和它就会跟别的进程抢内存严重时触发 OOM Killer直接把 mysqld 杀掉。我在云服务器上见过不少事故用户把 4G 服务器上的 MySQL 配置直接套用了 32G 服务器的配置文件innodb_buffer_pool_size24G结果系统一启动就卡死日志里全是 out of memory。2.2 连接线程和排序缓冲临时分配却常被忽略如果说 BP 是稳定占用那连接线程和各类临时缓冲就是“喝水”型占用来一个连接就分配一部分内存连接一多内存水涨船高。MySQL 每个连接在服务端至少要分配两个缓冲区sort_buffer_size和join_buffer_size。注意这两个参数是“每连接、每操作”都会分配的不是全局共享。假设你的sort_buffer_size4M同时有 200 个连接在跑 ORDER BY 排序那光排序缓冲就可能吃掉 800M。同理join_buffer_size在BKA、BNL等连接算法中也按连接分配。再加上read_buffer_size、read_rnd_buffer_size、net_buffer_length一个活跃连接的内存开销随随便便能到十几兆甚至几十兆。更隐蔽的是performance_schema。这个库默认是开启的它会在内存里维护大量统计表比如每个线程的事件记录、每个语句的摘要、锁等待信息等。我排查过一个小型实例业务量并不大但performance_schema居然吃了 2G 多内存。这个参数不像 BP 那样显眼但它真的会在后台悄悄积累。还有临时表。MySQL 8.0 默认临时表存储引擎是 TempTable内存中的临时表达到一定阈值后才转磁盘。如果业务里有大批量 GROUP BY、DISTINCT、子查询临时表内存占用会瞬间暴涨。2.3 关键认知MySQL 不释放内存是常态这里必须强调一个很多新手想不通的问题为什么我删掉了大量数据内存却不降原因有两个层面。第一InnoDB Buffer Pool 本身是“缓存”它里面存的数据页即使被删除和修改只要内存足够的空间MySQL 不会主动淘汰这些页。只有当需要加载新数据页且内存池已满时才会按照 LRU 算法换出一些旧页。所以删数据不会导致 BP 内存下降这是设计使然。第二glibc 的malloc和free机制决定了进程释放的内存未必交还给操作系统而是留在进程的堆内存空闲链表中供后续的分配复用。这是个优化策略假设 MySQL 某个瞬间并发很高分配了 2G 内存做排序排序完成后这 2G 内存并不会立刻归还给系统。如果下一次查询又需要排序直接复用这 2G 空闲内存比重新向内核申请要快得多。这个机制叫arena缓存。所以在top里看着 mysqld 的 RES 很高不代表它一直在用这些内存只能说“它曾经用过这些内存”。理解了这一点你就明白为什么网上很多教程教你“重启 MySQL 释放内存”是治标不治本。重启后内存确实降下来了但重新跑热数据后内存又会涨回来而且重启期间业务中断代价远大于那点内存收益。除非内存真的已经成为瓶颈且无法通过参数调整解决否则不要用重启来“释放内存”。3. 系统层面排查定位内存到底被谁吃掉3.1 用 top 和 pidstat 确认 mysqld 的实际内存排查第一步用top看进程排行top -o %MEM按内存降序排列找到 mysqld 那一行记下 PID然后用如下命令观察 mysqld 的实时内存变化pidstat -r -p PID 1 10pidstat会输出minflt/s每秒缺页数、majflt/s每秒主缺页数、VSZ和RSS。如果你发现majflt/s频繁出现非零值说明 MySQL 在不断访问磁盘上的数据页内存可能真的不够用了如果RSS一直稳定高位且majflt/s为零说明数据都在内存里性能是好的只是数字看着吓人。再看一下整机的内存压力cat /proc/meminfo重点关注CommitLimit和Committed_AS。Committed_AS是内核承诺给所有进程的内存总和如果它超过CommitLimit系统启用 overcommit 后可能触发 OOM。3.2 查看 MySQL 内部内存统计视图MySQL 5.7 及以上版本提供了内存统计表可以直接查询各内存组件的使用量SELECT * FROM sys.memory_by_thread_by_current_bytes;这个视图按线程展示当前内存占用能看到哪些连接最“吃”内存。如果某个连接的内存占用异常高定位到PROCESSLIST_ID后可以结合SHOW PROCESSLIST看它在执行什么 SQL。再查全局的内存消耗状况SELECT EVENT_NAME, CURRENT_NUMBER_OF_BYTES_USED FROM performance_schema.memory_summary_global_by_event_name ORDER BY CURRENT_NUMBER_OF_BYTES_USED DESC LIMIT 20;这个查询会列出所有内存事件memory event的当前使用量。我一般按字节数排序重点看前二十项。里面常见的几类如下所示。EVENT_NAME 关键字对应内存区域memory/innodb/buf_buf_poolInnoDB 缓冲池memory/sql/Query_cache查询缓存8.0 已移除memory/sql/thd::main_mem_root连接线程基础内存memory/sql/THD::mem_root语句执行内存memory/sql/derived_table派生表memory/performance_schema性能字典自身内存如果performance_schema相关的 EVENT_NAME 占到了总内存很大比例可以考虑关闭它或缩小它的采集项配置。生产环境中很多性能监控工具如 PMM、Prometheus mysqld_exporter依赖它提供指标不能全关但可以调整performance_schema_*_size相关参数来控制采集表的大小。4. 参数优化抓住核心配置逐项调整4.1 InnoDB Buffer Pool设置合理的上限innodb_buffer_pool_size是 MySQL 内存设置里最重要也最敏感的一个参数。设置公式没有绝对标准但有一条安全底线总内存的 50% 到 70%同时必须留出给操作系统和 MySQL 其他结构连接线程、排序缓存、临时表、binlog cache 等的余量。如果服务器上只有 MySQL 一个数据库服务没有部署其他重量级应用可以参考总内存 8G innodb_buffer_pool_size 4G ~ 5G 总内存 16G innodb_buffer_pool_size 8G ~ 10G 总内存 32G innodb_buffer_pool_size 16G ~ 20G 总内存 64G innodb_buffer_pool_size 32G ~ 40G注意MySQL 8.0.30 及以后可以设置innodb_buffer_pool_size为动态值不需要重启。但是调整后要观察一段时间不能一次性从 4G 调到 20G容易在初始化缓冲池时造成性能抖动。还有一个细节innodb_buffer_pool_instances。如果 BP 设置得很大比如超过 16G建议把实例数调大比如设成 8 或 16。每个 Buffer Pool Instance 有独立的 free list 和 mutex能减少并发访问时的锁竞争。这个参数在 MySQL 8.0.28 之后可以在线调整但注意它只能整倍数变化。4.2 连接数与各类 buffer防止“蚂蚁搬家”式占用max_connections这个参数是内存占用的乘法器。每增加一个连接就要预留一组线程栈、net buffer 和可能用到的排序/连接缓冲。如果max_connections设成 1000但实际业务只有 200 并发那剩下的 800 个连接虽然没建立但 MySQL 需要按最大值预留线程缓存内存开销照样存在。建议按实际业务并发设置一般是 200 到 500不要盲目设成 32767。配合max_used_connections指标观察线上运行一段时间后看SHOW GLOBAL STATUS LIKE Max_used_connections的值max_connections设置为这个峰值的 1.5 到 2 倍即可。排序和连接缓冲的调整策略更简单能小则小需要用时再临时调大单个会话的值。sort_buffer_size 2M join_buffer_size 2M read_buffer_size 1M read_rnd_buffer_size 1M很多教程把sort_buffer_size设成 64M这是误人子弟。排序缓冲按连接分配200 个连接每个 64M瞬间 12.8G 没了。通常 2M 到 4M 完全够小查询用大排序可以通过增大磁盘临时表的容量或者优化 SQL比如加索引避免 filesort来解决而不是靠堆内存。如果你有特定的大排序需求可以在会话级别临时设大SET SESSION sort_buffer_size 64 * 1024 * 1024;这样只影响当前连接不会波及全局。4.3 临时表内存阈值避免 Group By 拖垮内存如果业务查询中有大量GROUP BY、DISTINCT或派生表临时表会频繁从内存表转成磁盘表。这里有一个关键参数tmp_table_size和max_heap_table_size两者取较小值作为内存临时表的大小上限。默认配置下这两个参数可能是 16M 到 32M对于复杂报表查询确实不够。但是同样要注意“每连接分配”的特性。我通常把这两个参数设置在 64M 到 128M 之间然后监控Created_tmp_disk_tables和Created_tmp_tables状态值。如果磁盘临时表占比过高说明内存临时表太小SQL 需要中转磁盘如果内存临时表占用本身异常高说明 SQL 写得有问题需要优化而不是加内存。判断方法SHOW GLOBAL STATUS LIKE Created_tmp%;当Created_tmp_disk_tables / Created_tmp_tables的比例大于 25% 时才值得考虑调大内存临时表参数否则保持默认即可。4.4 performance_schema低调的内存吞噬者MySQL 5.7 之后performance_schema默认开启意在采集各类性能事件。但它内部每个采集项都有内存开销。举个例子events_statements_summary_by_digest会缓存所有 SQL 语句的指纹摘要默认情况下最多缓存 1000 种语句模式如果业务里动态 SQL 非常多这个表会持续增长。处理方式有两个方向如果线上不需要细粒度性能诊断可以关闭performance_schema OFF但副作用是很多监控工具比如 mysqld_exporter 的部分指标拿不到数据。所以我更推荐第二个方式按需裁剪采集项。performance_schema_max_table_instances 1000 performance_schema_max_thread_instances 500 performance_schema_max_statement_classes 200具体裁剪哪些项要结合查询结果来看SELECT EVENT_NAME, CURRENT_NUMBER_OF_BYTES_USED FROM performance_schema.memory_summary_global_by_event_name WHERE EVENT_NAME LIKE %performance_schema% ORDER BY CURRENT_NUMBER_OF_BYTES_USED DESC;把占用最大的几个采集项单独设小。这需要一点耐心但效果明显。4.5 其他容易被忽略的内存选项下面这几个参数虽然不显眼但在特定业务场景下能影响几百兆甚至上G的内存。table_open_cache打开表缓存每个缓存条目都有元数据和分区信息。如果表非常多几千张这个值设成 2000 的默认值可能不够用但设成 10000 又会增加内存。结合Open_Tables和Opened_tables状态值来判断。innodb_log_buffer_size默认 16M 通常没问题。如果日志写入非常频繁大量更新、删除可以调到 64M减少日志刷盘次数。这个参数对内存影响不大但容易被忽略。innodb_adaptive_hash_index自适应哈希索引默认开启。它在高并发点查场景能提升性能但也会消耗内存。如果表上的等值查询不多或者内存非常紧张可以考虑关闭。注意这个参数在 8.0 中仍然是动态的修改后观察响应性能再确定是否长期生效。max_heap_table_size和tmp_table_size前面提过放一起说取小值生效。再补充一个binlog_cache_size它只在事务提交时分配默认 32K。如果业务中有大批事务这个值过小会导致磁盘临时写入频繁过大则每个连接都要预留空间。一般不要超过 1M除非你确认有大事务场景。5. 实操记录一次 16G 内存服务器的完整排查过程5.1 现场信息收集为了让你少走弯路我用案例方式完整走一遍流程。假设这是一台 16G 内存的云服务器运行 MySQL 8.0.34部署了 4 个 Java 微服务合计占用约 4G 内存。报警记录显示内存使用率 93%但服务并未宕机只是频繁触发 swap。登录服务器后的操作顺序如下。第一步确认整机内存分配free -h输出结果为total used free shared buff/cache available Mem: 15Gi 8.1Gi 1.2Gi 181Mi 5.7Gi 7.0Giused 8.1Gavailable 7G表面上看还有余量但能看到已经出现 swap 使用了。再看 swapswapon --show发现 swap 分区已经用掉 512M说明内存压力确实存在不止是“看着高”这么简单。第二步定位 mysqld 的实际内存占用top -p $(pgrep mysqld) -b -n 1mysqld 的 RES 显示 6.8G。然后查看 MySQL 内部的详细内存统计SELECT EVENT_NAME, CURRENT_NUMBER_OF_BYTES_USED/1024/1024 AS MB FROM performance_schema.memory_summary_global_by_event_name ORDER BY CURRENT_NUMBER_OF_BYTES_USED DESC LIMIT 15;结果中最显眼的几项memory/innodb/buf_buf_pool5.0Gmemory/sql/THD::mem_root380Mmemory/sql/derived_table226Mmemory/performance_schema800Mmemory/innodb/adaptive_hash_index365M从这个结果能看到两个异常点连接线程相关内存 380M 偏高说明当前活跃连接数量不少且涉及复杂查询derived_table 占 226M说明有大量派生表在内存中处理performance_schema 占 800M对于一个 16G 服务器来说偏大。第三步查看当前连接数和状态SHOW GLOBAL STATUS LIKE Threads_connected; SHOW GLOBAL STATUS LIKE Max_used_connections;Threads_connected当前 280Max_used_connections340。再查看SHOW PROCESSLIST发现其中有大量来自同一个应用服务的连接正在执行带ORDER BY的列表查询。第四步确认这些连接的内存分配参数SHOW VARIABLES LIKE sort_buffer_size; SHOW VARIABLES LIKE join_buffer_size; SHOW VARIABLES LIKE max_connections;排序缓冲 4M、连接缓冲 4M、最大连接数 1000。按最大连接数 1000 算光排序和连接缓冲就可能分配 8G加上基础线程内存符合现状。5.2 优化动作与效果基于现场数据我做了以下调整innodb_buffer_pool_size从 6G 调到 5G。为什么调小不是因为它本身不正常而是因为这台服务器还要跑 Java 应用又开启了 swap。留出更多内存给系统级缓存和 Java 堆避免 OOM。max_connections从 1000 调到 500。根据Max_used_connections只有 340500 完全够用但在内存层面砍掉了近一半的预留线程空间。sort_buffer_size和join_buffer_size都从 4M 降到 2M。新版 MySQL 是动态分配机制小查询用不了那么多大查询在会话级临时调大。performance_schema保持开启但把一些非必要的采集表关掉UPDATE performance_schema.setup_instruments SET ENABLED NO WHERE NAME LIKE wait/%;注意这个操作要谨慎会影响后续诊断数据的收集。我更推荐在配置文件里加入performance_schema_max_table_instances 500 performance_schema_max_thread_instances 300 performance_schema_max_statement_classes 150tmp_table_size从 32M 调到 64M同时把max_heap_table_size也调到 64M。调整完后重启 MySQL参数里有需要重启生效的项观察两周。第一天的内存情况mysqld RES 5.1G free available 9.4G 使用率 42%七天后的稳定状态mysqld RES 5.4G free available 8.2G 使用率 48% swap 使用 0K整体内存压力大幅缓解且从监控看查询响应时间波动不大。我特别注意到由于 sort_buffer 调小部分复杂排序 SQL 的执行时间从 80ms 涨到 120ms可接受但如果业务更敏感我会用创建合适索引来消除 filesort而不是开大 buffer。5.3 经过较长时间运行操作系统关闭了大页内存这里有个后验细节。服务器在调整后跑了大概一个月某天突然发现free -h里 buff/cache 涨到了 7G 多而 mysqld 的 RES 只有 3.8G。一开始有点疑惑以为是 MySQL 数据访问变少了。后来查了 IO 状态发现是业务在做一个大范围的表扫描操作操作系统把扫描到的数据页都缓存下来了属于正常现象不需要处理。数据扫描结束buff/cache 会逐步回落。所以说内存优化不是一次性工作需要持续监控并理解各类内存的真实含义。看到内存高先别慌区分“缓存型占用”和“消耗型占用”前者是朋友后者才是敌人。6. 常见问题与排查技巧实录6.1 问题一为什么执行大查询后内存涨了不降这是最高频的问题。前面讲过 glibc 的 arena 缓存机制这里再展开一下。当 MySQL 执行一个需要 500M 排序缓冲的查询时malloc会向内核申请 500M 内存。查询执行完调用了free这 500M 内存被释放但 glibc 并没有马上用munmap把内存段归还内核而是放在进程的空闲链表中。这样下次排序时MySQL 可以直接从空闲链表取内存省去了系统调用开销。从外部看mysqld 的 RES 一直保持在高位即使空闲链接都释放了也不会降。这不能通过“调参数”来解决因为这是运行库层面为了性能而做的取舍。应对办法有两个方向第一种如果内存非常紧张想强制让进程归还内存可以用malloc_trim相关工具但 MySQL 官方并未内置需要挂载到进程里操作风险很高。生产环境我不建议这样做。第二种从源头限制单条大查询的内存使用。在 MySQL 中没有像max_memory_size这样直接限制所有内存去向的单一变量但可以限制单条 SQL 的执行时间max_execution_time或者对特定用户设置资源组限制。MySQL 8.0 的资源组功能可以给线程组设定 CPU 和内存限制但内存限制只有 virtual memory 维度实际效果有限。所以我的结论是大查询导致的内存残留能不处理就不处理。只要还有 available 内存硬件层面撑得住就别折腾。真到了 OOM 边缘优化 SQL 才是治本。6.2 问题二mysqld 被 OOM Killer 杀死常见模式一种常见模式是MySQL 的innodb_buffer_pool_size设成了物理内存的 80%再加上连接线程、临时表、排序缓冲的消耗在业务高峰一下越过内存红线触发内核 OOM Killer。因为 OOM Killer 的分值oom_score是根据进程内存占用大小来定的mysqld 作为最大的内存占用者经常被优先选中。查看内核日志确认dmesg | grep -i oom journalctl -k | grep -i oom如果找到类似 “Out of memory: Kill process 12345 (mysqld), score 750” 的记录说明确实是 mysqld 被杀了。对策修改/proc/PID/oom_score_adj保护 mysqld 进程。写进 systemd service 文件的ExecStartPre或/etc/sysctl.conf都行但最保险的方式是在 MySQL 的 systemd unit 里加OOMScoreAdjust-800把 mysqld 的 OOM 分数调低让它不容易被选中。但这不是万能药如果系统整体内存真的耗尽内核还是会根据各种因素挑一个进程杀掉所以 OOMScoreAdjust 只起到降低概率的作用。根子还是要把内存占用控制住。另外如果使用非 systemd 方式管理 MySQL可以在启动脚本里加上echo -800 /proc/$(pgrep mysqld)/oom_score_adj这种“保护”仅限手动启动场景且每次启动后都要执行。6.3 问题三MySQL 内存缓慢增长怀疑是内存泄漏MySQL 本身的稳定性已经很高真正因为代码缺陷导致的内存泄漏相对少见。更多情况是以下原因第一performance_schema的某些表如果开启了sum字段更新会持续为语句、等待事件分配内存导致内存曲线缓慢上升。针对这个场景可以定期清理TRUNCATE TABLE performance_schema.events_statements_history_long;第二Prepared Statement 没有正确释放。客户端每执行一次PREPARE就会在服务端保存一份解析后的 SQL 和参数类型如果连接不断开这些资源不会释放只会在超过max_prepared_stmt_count或连接关闭时才清理。检查应用层是否有PreparedStatement未关闭的逻辑是 MySQL 内存慢涨排查中的高性价比动作。第三临时内存表碎片化。内存表MEMORY 引擎或者 TempTable 引擎在频繁增删后会产生碎片导致内存总量只涨不降。如果是 MEMORY 引擎的业务表考虑改造成 InnoDB 并优化索引。如果确认内存确实持续增长而业务没有对应增长可以用性能字典的memory_summary_global_by_event_name多次采样对比找出哪类 EVENT_NAME 在持续增长然后按图索骥去查对应的连接和 SQL。6.4 排查技巧速查表症状首选命令/查询紧急处置内存占用高但可用内存充足free -h看 available不需要处置mysqld RES 持续上涨多次查询 memory_summary_global_by_event_name 对比按 EVENT_NAME 定位组件频繁 swapvmstat 1 10看 si/so调小 BP降 max_connections出现 OOMdmesggrep oom连接数多但并发不高SHOW STATUS LIKE Threads_connected调低 max_connections检查连接池配置排序后内存不释放topRES 高位但 stable无需处理观察 availableperformance_schema 内存大查询 memory_summary_by_event_name裁剪采集项或关闭7. 调优之外的长期策略参数调优能在短期内缓解内存压力但真正想要根治需要从架构和习惯两个层面下手。第一层监控体系建设。给 MySQL 配上 mysqld_exporter Prometheus Grafana 是基础方案重点盯住四个指标process_resident_memory_bytes、process_virtual_memory_bytes、mysql_global_status_threads_connected、mysql_global_status_innodb_buffer_pool_pages_free。有了趋势数据你能在内存告警之前看到“连接数在爬升”“空闲页在减少”而不是等问题爆发了才去现场救火。第二层SQL 治理。大部分内存问题最终都能追溯到某几条 SQL。可以定期查看慢查询日志重点关注ORDER BY、GROUP BY、多表JOIN且没有走索引的语句。一条 10 万行数据的全表排序可能就吃掉 100M 内存如果这类语句一分钟跑一次内存压力自然大。SQL 优化能从根本上减少临时表和排序缓冲的申请次数。第三层容量评估与基线管理。每台服务器上的 MySQL 内存占用并不是固定值它和业务流量密切相关。建议每周或者每次大版本发布后记录一组基线数据连接数、QPS、内存占用率建立正相关性分析。比如“当 TPS 达到 2000 时内存占用约 5.2G”有了这种经验数据下一次容量规划就有据可依。第四层定期清理连接泄漏。查代码里的数据库连接管理看看连接是否在 finally 块中关闭连接池的空闲连接超时时间是否合理。曾经遇到过一个应用把连接池最大连接数设到 500 而实际只需要 50导致 MySQL 端始终保持大量空闲连接每个连接 3M 左右白白浪费 1G 多内存。8. 一些心里话排查 MySQL 内存问题最考验人的不是会不会敲命令而是遇到“看着很吓人的高内存”时还能不能冷静分析。我刚入行的时候看到free显示 used 90% 就想重启 MySQL后来被前辈拦下“你看看 buff/cache”。现在回头看那些年踩过的坑都成了判断经验。如果你现在正被这个问题困扰我的建议是先花十分钟做诊断再花五分钟想清楚业务是否真的受影响。如果没有性能下降没有 swap没有 OOM大可不必纠结内存数字。如果有从 Buffer Pool 这个最大头开始调然后是连接数再是各类 buffer最后考虑 SQL 层面。这个顺序记下来你基本上能解决 70% 的 MySQL 内存焦虑。剩下的 30%就要靠对业务特征的理解和长期监控数据的沉淀了。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

离合器设计流程详解:从膜片弹簧参数计算到故障排查 2026/9/26 14:04:37

离合器设计流程详解:从膜片弹簧参数计算到故障排查

你如果翻过几本汽车构造或者机械设计的教材,大概率会在传动系统那一章看到“离合器”这三个字。教材里通常讲得很简略:一个圆盘、一个压盘、几根弹簧,摩擦结合、分离动力,似乎三言两语就能说完。但真要动手做一个离合器设计&#…

阅读更多 →
OpenClaw imageModel 配置指南:TaoToken 统一 Key 接入与 settings.json 骨架 2026/9/26 14:04:31

OpenClaw imageModel 配置指南:TaoToken 统一 Key 接入与 settings.json 骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
国产算力全线兑现背后:用 TaoToken 统一 Key 打通 AI 编程工具链的 config.toml 骨架 2026/9/26 14:04:31

国产算力全线兑现背后:用 TaoToken 统一 Key 打通 AI 编程工具链的 config.toml 骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Spring Boot+大数据驱动:海河沿岸城市双修景观画像系统设计实践 2026/9/26 14:04:25

Spring Boot+大数据驱动:海河沿岸城市双修景观画像系统设计实践

做毕设做到“大数据 Spring Boot”这个组合,大多数人第一反应是:这俩怎么凑一块?再往下看,还有“海河沿岸城市双修景观画像系统”,又冒出来一个城市规划领域的词。实际上,这套项目拆开来看就三件事&#x…

阅读更多 →
从零掌握 AI Skill 编写:Markdown 文件结构、调试与实战技巧 2026/9/26 14:04:18

从零掌握 AI Skill 编写:Markdown 文件结构、调试与实战技巧

1. 从零理解 Skill 到底是什么很多人第一次听到 Skill 这个词,脑子里浮现的是游戏里的技能树,或者是某个插件市场里可以一键安装的功能包。但如果你真正动手写过、改过、调试过 Skill,就会发现它更像是一份写给 AI 的"岗位说明书"—…

阅读更多 →
Allure测试报告实战:从pytest到CI的质量可视化与团队复盘 2026/9/26 14:04:18

Allure测试报告实战:从pytest到CI的质量可视化与团队复盘

自动化测试做到一定程度,大家拼的其实不是脚本写法,而是结果表达能力。我经历过无数个这样的早晨:昨晚流水线跑完一千多条用例,第二天全组人在CI控制台前翻输出,却没人能立刻说清楚到底挂了几条、挂在哪。Allure报告正…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉