当我们碰到数据库响应慢的时候,除了数据库自己的问题,磁盘读写可能是其中一个值得怀疑的因素,此时就可以用dd来测试磁盘的读写速度。
Linux的dd指令,可以用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。
man的说明,言简意赅,
dd - convert and copy a file
dd的参数说明,
if=file 输入文件名,缺省为标准输入。 of=file 输出文件名,缺省为标准输出。 ibs=bytes 一次读入 bytes 个字节(即一个块大小为 bytes 个字节)。 obs=bytes 一次写 bytes 个字节(即一个块大小为 bytes 个字节)。 bs=bytes 同时设置读写块的大小为 bytes ,可代替 ibs 和 obs 。 cbs=bytes 一次转换 bytes 个字节,即转换缓冲区大小。 skip=blocks 从输入文件开头跳过 blocks 个块后再开始复制。 seek=blocks 从输出文件开头跳过 blocks 个块后再开始复制。(通常只有当输出文件是磁盘或磁带时才有效)。 count=blocks 仅拷贝 blocks 个块,块大小等于 ibs 指定的字节数。 conv=conversion[,conversion…] 用指定的参数转换文件。 iflag=FLAGS 指定读的方式FLAGS,参见“FLAGS参数说明” oflag=FLAGS 指定写的方式FLAGS,参见“FLAGS参数说明”
其中conv参数,可转换的值如下,
ascii 转换 EBCDIC 为 ASCII。 ebcdic 转换 ASCII 为 EBCDIC。 ibm 转换 ASCII 为 alternate EBCDIC。 block 把每一行转换为长度为 cbs 的记录,不足部分用空格填充。 unblock 使每一行的长度都为 cbs ,不足部分用空格填充。 lcase 把大写字符转换为小写字符。 ucase把小写字符转换为大写字符。 swab 交换输入的每对字节。 noerror出错时不停止。 notrunc不截短输出文件。 sync 把每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。
FLAGS参数说明,
append -append mode (makes sense only for output; conv=notrunc sug-gested) direct 读写数据采用直接IO方式。 directory 读写失败除非是directory。 dsync 读写数据采用同步IO。 sync 同上,但是针对是元数据。 fullblock 堆积满block(accumulate full blocks of input)(iflag only)。 nonblock 读写数据采用非阻塞IO方式。 noatime 读写数据不更新访问时间。
一看这些参数,有点懵了,直接来点儿硬菜,为了测试磁盘的写能力,可以执行这个,因为/dev/zero是一个伪设备,他只产生空字符流,对他不会产生IO,所以,IO都会集中在of文件中,of文件只用于写,所以这个命令相当于测试磁盘的写能力,写入100000个4k数据块,
[root@bisal opt]# time dd if=/dev/zero of=/opt/testrw.dbf bs=4k count=100000
100000+0 records in
100000+0 records out
409600000 bytes (410 MB) copied, 1.92835 s, 212 MB/s
real 0m1.929s
user 0m0.000s
sys 0m1.444s
P.S. count是指读多少个bs,可以直接写count=16G,规避文件系统cache,直接读写,不直接使用buffer cache。
如果要测试磁盘读的能力,可执行这个,因为/dev/sda1是一个物理分区,对他的读取会产生IO,/dev/null是伪设备,相当于黑洞,of到该设备不会产生IO,所以,这个命令的IO只发生在/dev/sda1,相当于测试磁盘的读能力,
[root@bisal ~]# time dd if=/dev/sda1 of=/dev/null bs=4k
^C140287+0 records in
140286+0 records out
574611456 bytes (575 MB) copied, 12.62 s, 45.5 MB/s
real 0m12.621s
user 0m0.037s
sys 0m12.340s
如果要同时测试读写,一个是物理分区,一个是实际的文件,对他们的读写都会产生IO(对/dev/sda1是读,对/opt/testrw.dbf是写,会实际生成文件,因此要确认磁盘空间充足),假设他们都在一个磁盘中,这个命令就相当于测试磁盘的同时读写能力,
[root@bisal opt]# time dd if=/dev/sda1 of=/opt/testrw.dbf bs=4k
^C56537+0 records in
56537+0 records out
231575552 bytes (232 MB) copied, 3.891 s, 59.5 MB/s
real 0m3.892s
user 0m0.000s
sys 0m2.522s
另外,注意一下,dd只能提供一个大概的测试结果,而且是连续I/O而不是随机I/O,理论上文件规模越大,测试结果越准确。同时,iflag/oflag提供direct模式,direct模式是把写入请求直接封装成I/O指令发到磁盘,非direct模式只是把数据写入到系统缓存就认为I/O成功,并由操作系统决定缓存中的数据什么时候被写入磁盘。
借了这个例子,可以看下缓存对读写的影响,
https://blog.csdn.net/rong11417/article/details/102654966
带缓存的读写,
每次清缓存的读写,
不用缓存,直接的读写,
如上提到的/dev/null和/dev/zero,还是有点儿区别,我们经常在脚本中或者crontab定义中使用到/dev/null。
/dev/null,外号叫无底洞,你可以向他输出任何数据,他通吃,并且不会撑着。他是空设备,也称为位桶(bit bucket)。任何写入他的输出都会被抛弃。如果不想让消息以标准输出显示或写入文件,那么可以将消息重定向到位桶。
/dev/zero,是一个输入设备,你可用他来初始化文件。该设备无穷尽地提供0,可以使用任何你需要的数目,他可以用于向设备或文件写入字符串0。主要的用处是用来创建一个指定长度用于初始化的空文件,就像临时交换文件。
例如,禁止标准输出,
cat $filename >/dev/null #文件内容丢失,而不会输出到标准输出.
禁止标准错误,
rm $filename 2>/dev/null #这样错误信息[标准错误]就被丢了
禁止标准输出和标准错误的输出,
cat $filename 2>/dev/null >/dev/null
参考链接,
https://www.cnblogs.com/sylar5/p/6649009.html
https://blog.csdn.net/xizaihui/article/details/53307578
https://blog.csdn.net/rong11417/article/details/102654966