主题
一、测试目的
在 MySQL 上线前,使用 fio 模拟 InnoDB 数据库的随机读写负载,验证磁盘 I/O 性能是否满足业务需求。
二、测试环境
| 项目 | 信息 |
|---|---|
| 操作系统 | Linux |
| 磁盘类型 | NVMe SSD |
| 测试路径 | /home/application/mysql/data/(MySQL 数据目录) |
| fio 版本 | 3.29 |
| IO 引擎 | libaio |
| 直写模式 | O_DIRECT(绕过页缓存) |
三、测试参数说明
| 参数 | 值 | 说明 |
|---|---|---|
bs | 16K | 模拟 InnoDB 数据页大小 |
rw | randrw | 随机读写混合 |
rwmixread | 70 | 70% 读 + 30% 写,贴近典型数据库负载 |
iodepth | 64 | I/O 队列深度 |
numjobs | 4 | 4 个并发进程 |
runtime | 60 | 持续 60 秒 |
direct | 1 | 绕过操作系统页缓存,直写磁盘 |
ioengine | libaio | Linux 异步 I/O |
四、测试命令
bash
# 安装 fio(如未安装)
yum install -y fio
# 执行测试(注意:不要在 /tmp 下跑,tmpfs 不支持 O_DIRECT)
fio --name=mysql_test \
--filename=/home/application/mysql/data/fio_test \
--size=10G \
--bs=16k \
--rw=randrw \
--rwmixread=70 \
--iodepth=64 \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting \
--ioengine=libaio \
--direct=1
# 测试完成后清理
rm -f /home/application/mysql/data/fio_test五、测试结果
5.1 汇总
| 指标 | 读 | 写 |
|---|---|---|
| IOPS | 30,500 | 13,100 |
| 带宽 | 476 MiB/s | 205 MiB/s |
| 平均延迟 | 2.76 ms | 13.1 ms |
| 数据量 | 27.9 GiB | 12.0 GiB |
5.2 读延迟分布
| 百分位 | 延迟 |
|---|---|
| 50% (P50) | 2,737 µs (2.7 ms) |
| 90% (P90) | 2,999 µs (3.0 ms) |
| 95% (P95) | 3,064 µs (3.1 ms) |
| 99% (P99) | 3,294 µs (3.3 ms) |
| 99.9% (P999) | 4,752 µs (4.8 ms) |
5.3 写延迟分布
| 百分位 | 延迟 |
|---|---|
| 50% (P50) | 13,042 µs (13.0 ms) |
| 90% (P90) | 13,566 µs (13.6 ms) |
| 95% (P95) | 13,829 µs (13.8 ms) |
| 99% (P99) | 14,091 µs (14.1 ms) |
| 99.9% (P999) | 26,608 µs (26.6 ms) |
5.4 磁盘利用率
| 项目 | 数值 |
|---|---|
| 磁盘利用率 | 78.1% |
| 总 I/O 请求 | 1,827,506 读 / 785,644 写 |
| CPU 占用 | usr 3.02% / sys 7.90% |
六、完整输出记录
mysql_test: (g=0): rw=randrw, bs=(R) 16.0KiB-16.0KiB, (W) 16.0KiB-16.0KiB, (T) 16.0KiB-16.0KiB, ioengine=libaio, iodepth=64
...
fio-3.29
Starting 4 processes
mysql_test: Laying out IO file (1 file / 10240MiB)
Jobs: 4 (f=4): [m(4)][100.0%][r=478MiB/s,w=205MiB/s][r=30.6k,w=13.1k IOPS][eta 00m:00s]
mysql_test: (groupid=0, jobs=4): err= 0: pid=35271: Fri Apr 17 16:10:14 2026
read: IOPS=30.5k, BW=476MiB/s (499MB/s)(27.9GiB/60008msec)
slat (usec): min=4, max=10312, avg= 7.58, stdev=21.93
clat (usec): min=126, max=36792, avg=2755.52, stdev=429.92
lat (usec): min=132, max=36799, avg=2763.23, stdev=430.14
clat percentiles (usec):
| 1.00th=[ 2376], 5.00th=[ 2474], 10.00th=[ 2507], 20.00th=[ 2606],
| 30.00th=[ 2638], 40.00th=[ 2704], 50.00th=[ 2737], 60.00th=[ 2769],
| 70.00th=[ 2835], 80.00th=[ 2900], 90.00th=[ 2999], 95.00th=[ 3064],
| 99.00th=[ 3294], 99.50th=[ 3458], 99.90th=[ 4752], 99.95th=[10028],
| 99.99th=[20055]
bw ( KiB/s): min=447200, max=511616, per=100.00%, avg=487655.26, stdev=2644.84, samples=476
iops : min=27950, max=31976, avg=30478.45, stdev=165.30, samples=476
write: IOPS=13.1k, BW=205MiB/s (215MB/s)(12.0GiB/60008msec); 0 zone resets
slat (usec): min=4, max=11289, avg= 8.48, stdev=36.46
clat (usec): min=521, max=48732, avg=13113.40, stdev=1007.18
lat (usec): min=531, max=48740, avg=13122.01, stdev=1005.72
clat percentiles (usec):
| 1.00th=[12125], 5.00th=[12387], 10.00th=[12518], 20.00th=[12780],
| 30.00th=[12911], 40.00th=[13042], 50.00th=[13042], 60.00th=[13173],
| 70.00th=[13304], 80.00th=[13435], 90.00th=[13566], 95.00th=[13829],
| 99.00th=[14091], 99.50th=[14222], 99.90th=[26608], 99.95th=[42730],
| 99.99th=[46924]
bw ( KiB/s): min=192288, max=217088, per=100.00%, avg=209593.82, stdev=849.83, samples=476
iops : min=12018, max=13568, avg=13099.61, stdev=53.11, samples=476
lat (usec) : 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.01%
lat (msec) : 2=0.03%, 4=69.76%, 10=0.14%, 20=30.00%, 50=0.05%
cpu : usr=3.02%, sys=7.90%, ctx=2393432, majf=0, minf=111
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
issued rwts: total=1827506,785644,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=64
Run status group 0 (all jobs):
READ: bw=476MiB/s (499MB/s), 476MiB/s-476MiB/s (499MB/s-499MB/s), io=27.9GiB (29.9GB), run=60008-60008msec
WRITE: bw=205MiB/s (215MB/s), 205MiB/s-205MiB/s (215MB/s-215MB/s), io=12.0GiB (12.9GB), run=60008-60008msec
Disk stats (read/write):
dm-2: ios=1824071/783985, merge=0/0, ticks=5020005/10275664, in_queue=15295669, util=100.00%, aggrios=1827506/785669, aggrmerge=0/11, aggrticks=5031247/10297555, aggrin_queue=15328802, aggrutil=78.10%
sdb: ios=1827506/785669, merge=0/11, ticks=5031247/10297555, in_queue=15328802, util=78.10%七、性能参考对照
| 磁盘类型 | 随机读 IOPS (16K) | 随机写 IOPS (16K) |
|---|---|---|
| 普通机械盘 HDD | 100-300 | 80-200 |
| SATA SSD | 20K-80K | 15K-50K |
| NVMe SSD (PCIe 3.0) | 50K-200K | 30K-120K |
| 高端 NVMe (PCIe 4.0) | 200K-800K | 100K-500K |
| 本次测试结果 | 30,500 | 13,100 |
八、结论
- 随机读性能良好:30,500 IOPS,P99 延迟 3.3ms,满足数据库读场景需求
- 随机写性能可接受:13,100 IOPS,P99 延迟 14.1ms,写延迟受队列深度影响
- 磁盘利用率 78.1%:说明在 4 并发 64 队列深度下磁盘压力较大,业务高并发场景需关注
- 总体评价:该 NVMe SSD 满足中小型数据库业务需求,适合当前 MySQL 部署
九、注意事项
- 测试路径必须在真实磁盘上:不要在
/tmp(tmpfs 内存文件系统)上跑,会报O_DIRECT错误 - 不要在 MySQL 运行期间测试:避免与业务 I/O 竞争,影响结果准确性
- 测试文件大小建议 ≥ 内存 2 倍:防止数据完全缓存在内存中导致测试失真
- 多测几次取平均值:单次测试可能存在偏差
- 测试前确认磁盘无其他负载:确保结果反映磁盘真实能力
