开篇引入
"老板让我采购一台MySQL服务器,你帮看看配置?" "32核CPU够不够用?" "256G内存配多大磁盘?" "SSD用哪种好,PCIe还是SATA?"
这些问题几乎每个DBA都会遇到。《高性能MySQL》第4章专门讲了硬件和操作系统优化,今天我们聊最核心的两个:CPU和内存。
MySQL的性能瓶颈在哪
MySQL的性能瓶颈通常来自三个方面:
1. CPU瓶颈:查询太复杂,大量排序、聚合计算,CPU打满。
2. I/O瓶颈:数据太多,内存装不下,大量磁盘读写。
3. 内存瓶颈:配置不当,内存溢出,OOM。
实际生产中,I/O瓶颈最常见(尤其是用机械硬盘时),CPU瓶颈次之,纯粹的内存瓶颈相对少见。
CPU选型:核数 vs 主频
这是最容易被搞混的问题。
两个目标,两种选择
低延迟场景(追求单个查询快):选择高主频的CPU
- 每个查询只用到一个CPU核心
- 主频越高,单核性能越强
- 适合OLTP小事务
高吞吐场景(追求并发处理能力):选择多核的CPU
- MySQL可以并行处理多个查询
- 更多核心 = 更高并发
- 适合复杂分析查询
Intel vs AMD
Intel Xeon Scalable(至强可扩展)
├── Bronze: 入门级,8核以下
├── Silver: 主流,12-24核
├── Gold: 高性能,24核以上
└── Platinum: 顶级,28核以上
AMD EPYC(霄龙)
├── 7002系列:最高64核
├── 7003系列:Zen3架构,更强单核性能
└── 性价比通常更高
怎么看MySQL用不用CPU
-- 查看当前查询的CPU使用情况
SHOW PROCESSLIST;
-- 查看连接数
SHOW STATUS LIKE 'Threads_connected';
-- 查看正在运行的查询数(关键指标)
SHOW STATUS LIKE 'Threads_running';
-- 如果Threads_running接近CPU核数,说明CPU是瓶颈
实战:定位CPU瓶颈
-- 查看最耗CPU的查询
SELECT
DIGEST_TEXT AS query,
COUNT_STAR AS exec_count,
SUM_CPU_TIME/1000000000000 AS cpu_seconds,
AVG_CPU_TIME/1000000000000 AS avg_cpu_seconds
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_CPU_TIME DESC
LIMIT 10;
⚠️ 注意:MySQL 8.0才支持SUM_CPU_TIME,旧版本看不到。
内存选型:容量配置的艺术
为什么内存重要
MySQL用内存做缓存。缓存命中时,从内存读数据;缓存未命中时,要从磁盘读。
磁盘I/O vs 内存访问:速度相差100-1000倍。
内存访问:纳秒级(~100ns)
SSD访问:微秒级(~100μs)
HDD访问:毫秒级(~10ms)
配置大内存不是为了"把数据都装进去",而是为了减少磁盘I/O。
InnoDB Buffer Pool
Buffer Pool是InnoDB的核心内存区域,用来缓存表数据和索引。
-- 查看Buffer Pool使用情况
SHOW ENGINE INNODB STATUS\G
-- 或者查询performance_schema
SELECT
POOL_ID,
FREE_BUFFERS,
DATABASE_PAGES,
MODIFIED_PAGES,
PAGES_DATA,
PAGES_DIRTY,
PAGES_FLUSH,
NUMBER_PAGES_READ,
NUMBER_PAGES_WRITTEN
FROM performance_schema.INNODB_BUFFER_PAGE_LAZY;
推荐配置:
[mysqld]
# 生产环境:设置为可用内存的70-80%
innodb_buffer_pool_size = 128G
# 分成多个实例,减少锁竞争(建议不要超过实例数)
innodb_buffer_pool_instances = 8
# 预加载Buffer Pool(加速重启后的启动)
innodb_buffer_pool_load_at_startup = ON
工作集(Working Set)
不是所有数据都需要放内存。MySQL真正需要的,是工作集——经常被访问的那部分数据。
-- 查看哪些表被访问最多
SELECT
OBJECT_SCHEMA,
OBJECT_NAME,
COUNT_READ,
COUNT_WRITE,
COUNT_FETCH,
COUNT_INSERT,
COUNT_UPDATE,
COUNT_DELETE
FROM performance_schema.table_io_waits_summary_by_table
WHERE OBJECT_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
ORDER BY COUNT_READ DESC
LIMIT 20;
假设你的数据库有1TB数据,但80%的访问集中在20%的表上,那把热点数据放内存就够了,不需要买能装下整个数据库的内存。
内存配置检查清单
# 查看可用内存
free -h
# 查看MySQL进程内存使用
ps aux | grep mysqld
# 查看OOM killer日志(如果有内存问题)
dmesg | grep -i oom
常见配置错误:
[mysqld]
# 错误:Buffer Pool设置太大,超过物理内存
innodb_buffer_pool_size = 256G # 实际只有128G内存
# 错误:多个内存配置项加起来超过物理内存
innodb_buffer_pool_size = 64G
key_buffer_size = 32G
query_cache_size = 16G
tmp_table_size = 16G
# 总共128G,超过物理内存!
推荐配置原则
1. Buffer Pool = 物理内存 × 70%
可用内存 合理Buffer Pool
128G 90G
256G 180G
512G 350G
保留30%给:操作系统缓存、连接、临时表、其他MySQL内存区域。
2. 其他内存配置项
[mysqld]
# MyISAM索引缓存(如果还用MyISAM)
key_buffer_size = 32M
# 临时表最大内存
tmp_table_size = 256M
max_heap_table_size = 256M
# 连接内存
max_connections = 2000
# 预估:max_connections × sort_buffer_size × 2
# 2000 × 2M × 2 = 8G
SSD vs HDD:性能差距有多大
2015年后,SSD基本成了MySQL服务器的标配。
性能对比
随机读取IOPS 顺序读取吞吐
HDD (7200RPM) ~100 ~150 MB/s
SATA SSD ~50,000 ~550 MB/s
NVMe SSD ~500,000+ ~3,500 MB/s
SSD的优势:
- 随机I/O性能提升100-1000倍
- 支持更多并发连接
- 消除I/O等待导致的查询延迟尖刺
SSD选购要点
1. 看DWPD(每日全盘写入次数)
DWPD = 1: 消费级,适合开发测试
DWPD = 3: 企业级,适合中等写入负载
DWPD = 10+: 高耐久型,适合高写入场景
MySQL的写入主要是:binlog、redo log、数据页刷新。选择DWPD≥3的企业级SSD。
2. 看容量和性能关系
SSD越满,性能越差(垃圾回收影响)。
160GB SSD满载 ← 性能可能只有320GB SSD满载的一半
建议:购买SSD容量 = 预计使用量的2倍
3. RAID配置建议
数据盘:RAID 10(性能+冗余)
日志盘:RAID 10 或 RAID 1(顺序写入为主)
备选:独立NVMe SSD作为日志盘
写入放大(Write Amplification)
SSD的特殊现象:实际写入量 > 应用写入量。
举例:写入4KB数据
1. SSD需要擦除512KB块
2. 把块内其他数据读出来
3. 合并新数据
4. 写回整个块
结果:实际写入512KB
写入放大率 = 128倍
优化建议:
- 不要把SSD写满,保留30%空闲空间
- 开启TRIM支持
- 合理配置InnoDB刷新策略
典型服务器配置方案
入门级(开发测试)
CPU: 8核 (Intel i7/Xeon Bronze)
内存: 32G DDR4
存储: 1TB SATA SSD
用途: 个人学习、小项目
预算: ~1万
小规模生产
CPU: 16核 (Xeon Silver)
内存: 128G DDR4
存储: 2TB NVMe SSD (RAID 1)
用途: 10-50并发,中小业务
预算: ~5万
中规模生产
CPU: 32-64核 (Xeon Gold/EPYC)
内存: 256-512G DDR4 ECC
存储: 4TB NVMe SSD (RAID 10)
用途: 100-500并发,中型业务
预算: ~15-30万
大规模生产
CPU: 128+核 (EPYC 7742/Intel Xeon Platinum)
内存: 1TB+ DDR4 ECC
存储: 多盘NVMe SSD + 高速存储
用途: 1000+并发,大型业务
预算: 50万+
性能监控与容量规划
判断当前瓶颈
-- CPU瓶颈特征
-- Threads_running 高,且持续上升
SHOW STATUS LIKE 'Threads_running';
-- I/O瓶颈特征
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_wait_free';
-- 如果这个值持续 > 0,说明Buffer Pool需要从磁盘读取
-- 内存瓶颈特征
SHOW GLOBAL STATUS LIKE 'Aborted_connects';
SHOW VARIABLES LIKE 'max_connections';
容量规划公式
方法1:基于TPS估算
# 假设单线程sysbench测试结果
TPS = 1000
# 需要达到10000 TPS
# 需要并发线程数 = 10000 / 1000 = 10
# 如果单核处理1000 TPS,需要10核CPU
方法2:基于内存估算
数据总量 = 500GB
热点数据比例 = 20%(100GB)
预留Buffer Pool = 100GB × 1.2 = 120GB
结论:至少配置128GB内存
小结
- CPU选型看场景:低延迟选高主频,高吞吐选多核
- 内存是缓存,不是存储:配置够放下工作集即可
- Buffer Pool占大头:通常设置为物理内存的70-80%
- SSD是标配:NVMe SSD性能最强,但也要考虑DWPD和容量
- 不要只看单指标:CPU、内存、I/O需要平衡配置
- 持续监控:定期检查瓶颈,调整配置
硬件选型没有标准答案,关键是匹配业务特点。TPCC 10000的OLTP系统和TB级数据分析系统,硬件配置思路完全不同。
上一篇:【第07篇】基准测试方法论——如何科学评估MySQL性能 下一篇:【第09篇】文件系统与磁盘IO——让MySQL数据写入飞起来
延伸阅读
- 《高性能MySQL》第4章 操作系统和硬件优化
- InnoDB Buffer Pool配置文档
- Intel/AMD CPU选型指南
- SSD评测网站:StorageReview、Tom's Hardware