在 Mysql 中执行大量插入时,似乎需要等待很长时间。我是否正确地假设我存在磁盘 I/O 问题?是的,我在虚拟机上运行 Mysql。
Innodb_buffer_pool hit rate is %100
innodb_flush_method = ''
innodb_log_file_size = 250M
innodb_flush_log_at_trx_commit=1
$iostat -dx 10
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
xvda 0.00 2514.09 0.10 1483.22 0.80 31958.44 21.55 39.04 26.00 0.64 94.91
xvda1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
xvda2 0.00 2514.09 0.10 1483.22 0.80 31958.44 21.55 39.04 26.00 0.64 94.91
dm-0 0.00 0.00 0.10 3983.82 0.80 31870.53 8.00 163.34 39.84 0.24 94.91
dm-1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
xvda 0.00 2206.21 0.00 1336.24 0.00 28342.74 21.21 41.85 31.43 0.72 96.02
xvda1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
xvda2 0.00 2206.21 0.00 1336.24 0.00 28342.74 21.21 41.85 31.43 0.72 96.02
dm-0 0.00 0.00 0.00 3542.44 0.00 28339.54 8.00 165.48 47.09 0.27 96.02
dm-1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
$ top
top - 11:57:19 up 88 days, 11:38, 3 users, load average: 1.44, 1.54, 1.60
Tasks: 80 total, 2 running, 78 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.7%us, 1.0%sy, 0.0%ni, 44.5%id, 53.2%wa, 0.0%hi, 0.0%si, 0.7%st
Mem: 16777216k total, 13791264k used, 2985952k free, 166988k buffers
Swap: 2129912k total, 44k used, 2129868k free, 7157368k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3910 mysql 15 0 13.2g 5.6g 6760 S 1.7 34.8 4:50.09 mysqld
1 root 15 0 10364 740 620 S 0.0 0.0 0:00.29 init
2 root RT -5 0 0 0 S 0.0 0.0 0:00.00 migration/0
3 root 34 19 0 0 0 S 0.0 0.0 0:02.77 ksoftirqd/0
4 root RT -5 0 0 0 S 0.0 0.0 0:00.00 watchdog/0
5 root 10 -5 0 0 0 S 0.0 0.0 0:00.08 events/0
6 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 khelper
7 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 kthread
9 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 xenwatch
10 root 10 -5 0 0 0 S 0.0 0.0 0:01.95 xenbus
15 root 10 -5 0 0 0 S 0.0 0.0 0:00.04 kblockd/0
16 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 cqueue/0
20 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 khubd
22 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 kseriod
84 root 15 0 0 0 0 S 0.0 0.0 0:00.01 khungtaskd
87 root 10 -5 0 0 0 S 0.0 0.0 1:37.10 kswapd0
88 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 aio/0
218 root 11 -5 0 0 0 S 0.0 0.0 0:00.00 kpsmoused
239 root 17 -5 0 0 0 S 0.0 0.0 0:00.00 kstriped
248 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 ksnapd
259 root 10 -5 0 0 0 S 0.0 0.0 1:56.45 kjournald
281 root 10 -5 0 0 0 S 0.0 0.0 0:01.04 kauditd
309 root 16 -4 12632 744 408 S 0.0 0.0 0:00.37 udevd
636 root 12 -5 0 0 0 S 0.0 0.0 0:00.00 kmpathd/0
637 root 12 -5 0 0 0 S 0.0 0.0 0:00.00 kmpath_handlerd
656 root 11 -5 0 0 0 S 0.0 0.0 0:00.00 kjournald
答案1
简单来说,是的。
主要指标是53.2%
CPU的等待时间。如果您的 I/O 等待百分比大于(1/CPU 核心数),那么您的 CPU 需要等待大量时间才能让磁盘子系统跟上。
插入会产生磁盘写入 I/O,这通常是带有硬盘驱动器子系统的虚拟磁盘最糟糕的情况。众所周知,HDD 的写入速度比读取速度慢。SSD 可以缩小这一差距,但写入时间仍然比读取时间慢。因此,任何写入操作都会比读取操作产生更大的负面影响。
此外,当您将大型数据库和/或高负载数据库与不是为重负载 I/O 设计且已经经历大量 I/O 的磁盘子系统(如 VM 的磁盘子系统)混合使用时,问题就会成倍增加,并产生严重的磁盘 I/O 问题。
除了将服务器移至具有针对 SQL 进行优化的磁盘子系统的专用机箱(这将是您的长期解决方案)外,最好的办法是从虚拟机(如 Web 服务器)中移除任何不必要的负载,然后只在其上运行基本框架和 SQL。此外,请确保您正在调整索引和查询,并尽可能在非高峰时段尝试运行大多数插入查询。
答案2
是的,你说得对,你遇到了磁盘 I/O 问题。顺便问一下,你为什么要使用innodb_flush_log_at_trx_commit=1
?它在高负载环境中效果不佳,innodb_flush_log_at_trx_commit=2
建议使用。但我不认为它会对你有帮助,因为你有大量插入,所以我假设事务率不会太高(每秒不会有几百个)。所以你应该考虑通过某种方式添加更多主轴来改进你的磁盘子系统。
答案3
作为一名反对者,我不得不反对一些分析。首先,我认为 iowait 时间可能极具误导性。它实际上只是在说,当 CPU 空闲时没有其他事情发生。换句话说,较低的 iowait 并不意味着磁盘不忙或系统没有等待,它只是意味着它有更好的事情要做,而不是在等待 io 完成时无所事事。
我个人认为 iostat 输出中的等待和服务时间信息量更大,尽管我并不喜欢这种输出格式,因为我发现它比 collectl 的输出更难读。无论如何,该输出中的等待时间只有 20-40 毫秒,这真的不算太糟糕。
-标记