MySQL性能瓶颈80%源于innodb_buffer_pool_size配置不当;需按活跃数据量×1.2~1.5设定,上限为物理内存75%,超80%易触发swap导致延迟飙升100倍。

看数据量和活跃度,再定内存大小
MySQL性能卡在哪,80%时候是内存不够——不是总内存少,而是 innodb_buffer_pool_size 没配够。它决定多少热数据能常驻内存,避免频繁读盘。
- 先估算“活跃数据量”:不是数据库总大小,而是每天被高频查询/更新的那部分(比如订单库中近30天的数据)
- 生产环境建议:缓冲池 = 活跃数据量 × 1.2~1.5,但不超过物理内存的75%(留至少4GB给OS和后台线程)
- 配太大反而坏事:超过80%时,Linux可能触发
swappiness交换,一次磁盘swap会让查询延迟飙升100倍以上 - 验证是否够用:
SHOW STATUS LIKE 'innodb_buffer_pool_%',重点看Innodb_buffer_pool_reads(每秒从磁盘读页数)——持续 > 50 就该扩容了
OLTP还是OLAP?CPU选型不能只看核数
同样是16核CPU,电商下单系统和报表导出系统,表现可能天差地别——因为MySQL对CPU的使用方式完全不同。
- OLTP场景(如用户登录、支付确认):单条SQL快才是关键,主频>核心数。推荐基础频率≥3.2GHz,睿频≥4.0GHz,比如
Intel Xeon Gold 6330或AMD EPYC 7413 - OLAP场景(如月度GMV统计):复杂JOIN+GROUP BY天然并行,核心越多越快。此时可降频保核,选32核但基础频2.8GHz的型号更划算
- 开发机别堆核:4核8线程(如
i5-12400F)足够跑本地压测,再多核心在单机MySQL里利用率很低,还拉高功耗和温度 - 别忽略NUMA:多路服务器上,若未启用
innodb_numa_interleave=ON,跨NUMA节点访问内存会慢30%以上
SSD不是买来就插上,I/O配置要对得上硬件能力
换上NVMe SSD后QPS没涨反跌?大概率是MySQL没“认出”这块盘的真实能力,还在按SATA节奏干活。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 查真实IOPS:
sudo fio -name=randread -ioengine=libaio -rw=randread -bs=4k -direct=1 -size=1G -runtime=60 -time_based -group_reporting,记下实际随机读IOPS - 把结果设进MySQL:
innodb_io_capacity设为实测值的70%,innodb_io_capacity_max设为实测值的200% - 机械盘或低配SATA SSD:这两个值分别设成200和400即可,设太高反而引发写放大
- 企业级SSD必须开
innodb_flush_method=O_DIRECT,否则OS缓存和InnoDB缓冲池双重缓存,浪费内存还增加一致性风险
并发连接数不是越大越好,线程资源有隐性成本
max_connections 调到10000,不代表真能扛住1万并发——每个连接背后都吃内存、占CPU上下文、争锁。
- 每个连接默认消耗约2MB内存(含排序缓存、临时表等),1000连接 ≈ 2GB额外开销
-
thread_cache_size建议设为max_connections的5%~10%,但上限别超64;设太高会导致空闲线程堆积,抢占调度器资源 - 真正瓶颈常在锁等待:用
SELECT * FROM performance_schema.data_lock_waits查谁在等锁,比盲目加核加内存更有效 - 连接池比调大
max_connections更治本:应用层用HikariCP或Druid,把连接复用起来,数据库侧保持300~500连接通常就够用
硬件选型最常被跳过的一步,是没先跑通业务SQL的执行计划。再好的CPU,遇到全表扫描的慢查询也救不回来;再大的缓冲池,如果索引没建对,一样天天刷脏页。先用 EXPLAIN FORMAT=TREE 看几条核心SQL,比对着参数表调配置实在得多。










