数据库变慢时,如何判断物理机机械盘、SATA SSD与NVMe是否存在IOPS瓶颈?
数据库变慢时,单看“CPU只有30%”或“磁盘利用率接近100%”,都不足以判断存在IOPS瓶颈。更可靠的依据是:在同一时间窗口内,业务请求增加后,磁盘实际完成的I/O数量开始趋于平台,I/O队列和等待时间继续上升,数据库的读盘或日志同步等待同步增加,最终反映为查询响应时间、超时率或连接排队恶化。
机械盘、SATA SSD与NVMe的区别,主要体现在不同访问模式、并发深度下的处理能力和延迟,而不是一个固定的IOPS倍数。判断时既要确认数据库是否真正等待存储,也要排除CPU、内存、网络、锁竞争和低效SQL等替代解释;只有这些指标形成相互支持的证据链,才能决定换盘是否有价值,以及应该换到哪一类磁盘。
一、先建立观察窗口,让所有指标回答同一个问题
性能分析首先需要解决“是否发生在同一时段”。拿今天的CPU平均值,对比昨天的慢查询,再参考磁盘的瞬时峰值,很容易拼出一个不存在的因果关系。
建议保留一个业务正常窗口、一个变慢窗口,以及调整后的复测窗口。对短时抖动,可先按1秒采样连续观察数分钟;对批处理、备份和晚高峰,应覆盖完整事件。查询响应时间宜查看P95、P99,而不仅是平均值,同时记录请求到达量与完成量。
需要放在同一时间轴上的指标至少包括:
| 观察层 | 核心指标 | 要回答的问题 |
|---|---|---|
| 业务与应用 | 请求量、完成量、P95/P99、错误率、连接池等待、请求队列 | 变慢是服务处理慢,还是请求在进入数据库前已排队? |
| CPU | 各核心利用率、运行队列、用户态与内核态占比 | 是否有单核或多核计算饱和? |
| 内存 | 可用内存、换入换出、数据库缓存命中与物理读变化 | 是否因缓存不足或内存压力放大了磁盘访问? |
| 存储 | 读写IOPS、吞吐量、平均请求大小、等待时间、队列长度 | 是随机I/O、带宽、同步写延迟,还是设备异常? |
| 网络 | 流量、丢包、重传、连接往返时间 | 数据库之外的传输是否拖长了响应? |
| 数据库 | 执行时间、存储等待、锁等待、日志同步、活跃连接 | SQL时间具体消耗在哪一类工作上? |
观察窗口不仅要时间一致,还要统计口径一致。 例如业务指标是1分钟聚合,磁盘指标是1秒采样,应同时保留磁盘峰值和持续时间。一次持续两秒的队列尖峰,可能被分钟平均值完全掩盖,却已经造成一批请求超时。
还要确认数据库文件实际落在哪个设备上。物理机上可能同时存在系统盘、数据盘、日志盘,以及RAID控制器提供的逻辑卷。监控中一个/dev/sdX不一定是一块机械盘,一个逻辑卷也可能跨越多个设备。
在Linux上,可先查看挂载与块设备关系。下面的数据库路径应替换为实际数据目录:
findmnt -T /实际数据库数据目录
lsblk -o NAME,TYPE,ROTA,TRAN,SIZE,MOUNTPOINT
ROTA可辅助识别旋转介质,但在硬件RAID等场景下不能仅凭它确定底层磁盘类型。若系统只暴露RAID逻辑盘,还需要结合控制器信息确认成员盘、阵列状态和缓存策略。
二、指标A:IOPS发生变化时,同时看延迟、队列和请求大小
IOPS表示每秒完成的I/O次数,不表示每秒处理了多少条SQL。一条查询可能命中内存,也可能触发数百次读盘;一次块设备请求还可能由多个访问合并而来。因此,“每秒查询数高于磁盘IOPS”本身并不矛盾。
数据库常见的存储访问也不完全相同:
- 随机读取数据页,通常更关注小块随机读能力。
- 后台刷脏页,既涉及写入能力,也受刷盘节奏影响。
- 事务提交中的日志持久化,更关注同步写和尾延迟。
- 全表扫描、备份、恢复等大块访问,可能更接近吞吐量限制。
三类磁盘的差距,应放在相同负载条件下理解
以下是用于理解量级的参考,不是某个型号的实测结果,也不能作为采购验收值。这里主要讨论绕过操作系统页缓存、以小块随机读取为主的设备访问。
| 磁盘类型 | 低并发随机访问的常见表现 | 并发提高后的特点 | 数据库判断重点 |
|---|---|---|---|
| 机械盘 | 单盘随机IOPS常在几十到数百量级,等待时间通常为毫秒级 | 寻道和旋转限制明显,增加队列往往先增加延迟 | 随机读写是否让完成量停滞、队列持续堆积 |
| SATA SSD | 低队列深度下可达数千到万级IOPS,具体取决于介质和请求模式 | 合适条件下可达到数万乃至更高量级,但受接口、控制器和介质限制 | 随机I/O压力、同步写延迟与接口吞吐是否分别成为约束 |
| NVMe SSD | 低并发时可能与部分SATA SSD处于相近量级,也可能更快 | 更能发挥多队列和高并发能力,适当负载下可达到数十万IOPS或更高 | 实际并发是否足够,CPU、数据库锁及软件路径是否先饱和 |
机械盘还要区分转速和盘数;SSD则要区分读写比例、持续写入状态、可用空间、温度和型号设计。不能把一块NVMe在高队列深度下的随机读结果,直接当成数据库单事务提交能力。
一个简单估算能说明低并发限制:若一次I/O完成后才发起下一次,平均延迟为8毫秒,则理论完成量约为“1÷0.008=125次/秒”;延迟为100微秒时约为1万次/秒,40微秒时约为2.5万次/秒。这只是单个串行请求流的估算,尚未包含数据库执行、网络、锁和日志处理时间。
NVMe的高并发IOPS优势,不能自动转化为单条SQL或单次提交的同比例加速。
用四个指标判断“忙”是否已经变成“堵”
Linux上可使用sysstat提供的工具观察。以下命令均为只读采样,可在不同终端并行运行:
iostat -x -y 1 60
mpstat -P ALL 1 60
vmstat 1 60
iostat不同版本的字段名称略有差别,应重点查看:
r/s、w/s:设备每秒完成的读写请求数。rkB/s、wkB/s:读写吞吐量。r_await、w_await或await:请求从进入统计范围到完成的平均时间,包含排队影响。aqu-sz,部分版本显示为avgqu-sz:平均未完成请求数。%util:采样期间设备有I/O活动的时间占比。
%util对单块机械盘具有较强参考意义,但对并行能力较高的SSD、NVMe和RAID,接近100%不等于已经达到性能上限。反过来,平均利用率不高,也不能排除少量同步写请求出现严重尾延迟。
更有判断力的变化是:到达压力增加,完成IOPS却增长有限,同时队列与等待时间持续上升。 若业务延迟也在这一阶段恶化,才值得进一步确认存储瓶颈。
在统计口径一致、负载相对稳定时,可以用“平均未完成请求数≈完成IOPS×平均响应时间”做粗略核对。例如125 IOPS、平均等待120毫秒,对应约15个未完成请求。不要把物理盘与逻辑卷的数据混在一起计算,也不要把这条关系当作瞬态故障的精确公式。
IOPS不高,也可能是带宽或同步写在限制
吞吐量约等于IOPS乘以平均请求大小。按二进制单位计算:
- 1万IOPS,每次4 KiB,约为39.1 MiB/s。
- 1万IOPS,每次64 KiB,约为625 MiB/s。
同样的IOPS,请求大小不同,对设备的压力可能完全不同。SATA SSD在大块访问时可能先遇到接口或设备吞吐限制,而不是小块随机IOPS限制。
另一种情况是日志同步:写入流量很小,但每次提交必须等待持久化完成。此时应关注同步写等待和提交P99,而不是仅以“IOPS没跑满”认定存储没有问题。
三、指标B:让数据库等待与业务响应形成联动
发现磁盘队列增长,还需要回答第二个问题:数据库是否正在等待这些I/O?
下面是一组用于说明判断过程的模拟数据。场景为数据文件位于单块机械盘,业务以随机读取为主;这些数字不代表实际监控结果。
| 指标 | 正常窗口 | 变慢窗口 |
|---|---|---|
| 业务请求到达量 | 180次/秒 | 420次/秒 |
| 业务请求完成量 | 180次/秒 | 230次/秒 |
| 查询P95 | 24毫秒 | 480毫秒 |
| 查询P99 | 60毫秒 | 1500毫秒 |
| CPU用户态占比 | 18% | 24% |
| 磁盘完成IOPS | 70 | 125 |
| 磁盘平均等待 | 9毫秒 | 120毫秒 |
| 平均未完成请求数 | 约0.6 | 约15 |
| 数据库活跃连接 | 35 | 220 |
| 等待特征 | 存储等待较少 | 数据页读取等待明显增加 |
| 其他变化 | 无持续换页 | 无持续换页,锁等待未明显增加 |
这组变化支持的判断是:请求压力上升后,机械盘完成量增长有限,磁盘队列与等待时间明显恶化;数据库读取等待和业务尾延迟同步上升,活跃连接积压。CPU没有同步进入计算饱和,内存换页和锁竞争也未提供更强的解释,因此存储随机读取能力不足成为主要候选。

但它还没有证明“所有慢SQL都是磁盘导致的”。仍应查看是否有新SQL、执行计划变化或批量任务,突然增加了每个请求需要读取的页数。
缓存命中率要与物理读次数一起看
命中率保持在99%以上,不等于磁盘压力没有变化。数据库逻辑访问总量增长时,即便命中率基本不变,落到存储上的访问仍可能显著增加。
例如逻辑页请求从每秒1万次增至10万次,未命中比例仍为0.5%,按同一统计口径估算,未命中次数就从每秒50次增至500次。对机械盘而言,这可能足以改变排队状态。
MySQL/InnoDB可以结合缓冲池物理读与逻辑读计数的窗口增量分析,而不是只看启动以来的累计命中率。PostgreSQL可结合缓存命中、数据块读取及I/O等待观察;支持pg_stat_io的版本还可进一步查看I/O统计,时间类字段则需核验相关计时设置。
这些数据库计数不能机械等同于物理磁盘IOPS:操作系统缓存、预读、请求合并及数据库页大小都会改变对应关系。它们的价值在于解释“为什么这一时段存储需求增加”。
写入变慢,要拆开日志同步和后台刷盘
如果提交P99变差,先区分时间花在什么地方:
- 日志持久化等待增加,而吞吐量不大:更像同步写延迟问题。
- 后台刷脏页、检查点或批量写入增加,同时设备写队列变长:更像写入服务能力不足。
- 日志与数据共享设备,读写延迟同时恶化:可能存在相互干扰。
- RAID重建、降级或缓存策略变化后出现退化:优先确认阵列状态,而不是直接归因于盘型。
锁等待也不总是独立原因。事务等待I/O时仍持有锁,可能让其他事务随后进入锁等待。需要观察谁先变化,而不是看到锁等待就立即排除磁盘。
四、排除替代解释:哪些现象不足以支持换盘
多指标分析的目的不是把所有问题归到存储,而是找到更能解释时间关系的候选原因。
| 候选瓶颈 | 常见联动表现 | 与存储瓶颈的区分方法 |
|---|---|---|
| CPU计算 | 单核或多核接近饱和,运行队列增长,SQL计算时间增加 | 查看各核心,而非只看整机平均值;确认磁盘等待是否同步恶化 |
| 内存压力 | 可用内存减少,持续换入换出,数据库物理读增加 | 区分数据文件I/O与换页I/O,确认谁先发生 |
| 锁竞争 | 锁等待、阻塞事务、连接积压增加,磁盘可能不忙 | 找到阻塞链,检查持锁事务是否也在等待存储 |
| 网络 | 应用端耗时上升,数据库执行时间相对稳定,重传或往返时间增加 | 对比客户端总耗时与数据库侧执行耗时 |
| 应用排队 | 连接池或线程池等待增加,数据库接收请求量并未同步上升 | 确认请求是在进入数据库之前,还是进入之后排队 |
| SQL退化 | 扫描行数、读取页数或临时文件增加,特定SQL集中变慢 | 核对执行计划与单位请求I/O需求,而非仅看设备负载 |
CPU的iowait只能作为辅助信号。它反映CPU空闲且存在未完成I/O的相关时间,不直接表示某条SQL等待了多久,也不能单独证明磁盘已饱和。多核服务器上即便存储等待严重,整体iowait也可能并不突出。
内存问题尤其容易被误判成磁盘问题。缓存不足导致物理读持续增加,最终确实会让磁盘排队;但根因可能是工作集扩大、内存配置变化或扫描行为。换成SSD能缓解症状,却未必比减少读取量或恢复合理缓存更合适。
还要检查I/O错误、设备超时、温度节流以及RAID异常。它们造成的延迟恶化属于存储侧问题,但不一定是正常工作状态下的IOPS容量不足。
五、形成判断:区分“需求过高”与“设备能力不足”
比较稳妥的存储瓶颈判断,需要以下条件在同一窗口内相互支持:
- 业务完成量跟不上到达量,响应时间或排队持续恶化。
- 数据库数据读取、写入或日志同步等待明显增加。
- 对应设备出现完成量平台、队列增长、延迟升高,或与慢请求对应的同步写尾延迟异常。
- CPU计算、内存换页、锁、网络和应用排队不能更好地解释这一变化。
- 存储压力下降后,数据库等待与业务延迟也随之回落。
第五点很重要。仅有“同时发生”属于相关证据;如果错峰备份、减少非关键批处理或在隔离环境降低I/O压力后,延迟随之改善,因果判断会更有说服力。生产环境中的调整应先评估业务影响,不应随意终止关键任务。
确认存储等待后,还需要区分两个问题:
单位请求的I/O需求是否异常增加? 如果某条SQL从读取几十页变成读取几十万页,优先检查索引、执行计划和查询范围。更快的磁盘可以减轻压力,但不能代替修正访问路径。
在合理访问模式下,设备是否仍无法满足目标延迟? 如果SQL与缓存行为基本稳定,业务增长后持续触及存储服务能力,升级才更有依据。
| 已确认的情况 | 更合理的处理方向 |
|---|---|
| 机械盘随机读取队列持续增长 | SSD升级通常有明显价值,同时保留SQL与缓存优化 |
| SATA SSD主要受大块吞吐限制 | 评估NVMe及实际PCIe链路能力,并复核文件系统、阵列和CPU路径 |
| SATA SSD高并发小块I/O受限 | 评估NVMe的并行能力,但需按业务读写比例验证 |
| 提交时间主要受同步写限制 | 比较同步写和尾延迟表现,不能只比较高队列深度IOPS |
| NVMe仍很忙,但CPU或数据库内部竞争先饱和 | 优先定位软件与计算路径,不宜继续按标称IOPS升级 |
| 存储异常伴随重试、超时、降级 | 先恢复正常状态,再判断是否需要扩容 |
这里的升级对象不是接口名称本身,而是能否在目标负载下维持可接受的延迟。不同SSD在持续写入、缓存耗尽和温度升高后的表现可能不同;涉及事务持久化,还必须评估掉电保护及端到端写入可靠性,不能通过降低持久化要求制造“性能提升”。

六、复测:验证的是瓶颈是否移动,而不只是跑分是否提高
复测应尽量保持数据量、SQL组合、并发、读写比例、缓存状态和持久化设置一致。至少对比正常负载、接近问题出现时的负载,以及短时突发三个窗口。
真实业务回放或隔离测试库比单一磁盘跑分更能说明数据库收益。若使用fio等工具,只应在明确隔离的测试设备或测试文件上进行,并核对目标路径、可用空间、读写模式和影响范围;不要对正在承载数据库的原始设备进行写测试,也不要让压测与生产业务争用同一存储资源。
对于机械盘、SATA SSD与NVMe,测试至少应区分低队列深度随机读、较高并发的混合读写,以及同步写场景。只拿高并发随机读结果,无法验证提交延迟。
复测结果可以按下面的方式解读:
- 磁盘等待、数据库存储等待和业务P99一起下降:支持原先存在存储约束。
- 磁盘指标改善,但业务延迟没有明显改善:存储可能只是次要瓶颈,或其他环节已成为主导。
- 吞吐提高后CPU、锁等待开始上升:瓶颈发生了转移,需要继续观察。
- 平均响应改善,但P99仍周期性尖峰:继续关联检查点、日志同步、后台任务和设备尾延迟。
下一次数据库变慢时,建议同时保留三组指标:“请求到达量、完成量、P95/P99、连接队列”描述业务影响;“磁盘IOPS、吞吐量、请求大小、等待时间、队列”描述存储状态;“各核心CPU、可用内存与换页、数据库I/O和锁等待、网络重传”排除替代解释。
只有这三组指标在同一时间窗口内形成一致变化,才能把“磁盘可能慢”收敛为可执行判断:该优化SQL和缓存、调整任务时段、修复存储异常,还是将机械盘或SATA SSD升级为更适合当前负载的存储设备。



