磁盘IO压测工具之dd命令(磁盘性能测试)
简介
dd 也是我们经常使用到的磁盘测试工具,Linux服务器装好系统之后,想要知道硬盘的读写是否能满足服务的需要,如果不满足硬盘的IO就是服务的一个瓶颈。我们可以使用dd命令简单进行测试,更为专业的测试可以使用上面描述的fio 工具:
time有计时作用,dd用于复制,从if读出,写到of。if=/dev/zero不产生IO,因此可以用来测试纯写速度。同理of=/dev/null不产生IO,可以用来测试纯读速度。bs是每次读或写的大小,即一个块的大小,count是读写块的数量。
dd是linux自带的磁盘读写工具,可用于测试顺序读写。 一般而言,磁盘读写有两种方式:BufferIO、DirectIO,DirectIO可以更好的了解纯磁盘读写的性能。
dd
命令是LINUX
下的一个命令行工具,用于数据转换和处理。dd
代表“数据复制”,它可以从一个设备或文件中读取数据,然后将数据写入到另一个设备或文件中。dd
命令可以用于多种用途,包括以下几个方面:
- 磁盘备份和克隆
- 数据恢复
- 空白文件创建
- 密码破解
dd命令的特点
- 灵活性:可以用于多种数据处理和转换操作,包括备份和克隆磁盘、数据恢复、磁盘清除、空白文件创建等。
- 可靠性:使用底层的块设备接口读写数据,能够完整地复制数据,保证数据的一致性和完整性。
- 高效性:可以使用多种缓存机制,提高数据传输速度,使得数据复制更加高效。
- 灵敏度:可以使用不同的块大小和缓存大小,根据需要进行调整,适应不同的硬件和数据传输需求。
- 通用性:可以在不同的操作系统和硬件平台上运行,具有很强的通用性。
dd命令的基本语法
dd
命令的基本语法如下:
1 | dd [option]... |
其中,option
是dd
命令的可选参数,用于指定dd
命令的功能和操作。
dd命令常用参数
dd
命令可以用指定大小的块来拷贝一个文件,并在拷贝的同时进行指定的转换。
参数 | 注释 |
---|---|
if=文件名 | 输入文件名,缺省为标准输入。即指定源文件。< if=input file > |
of=文件名 | 输出文件名,缺省为标准输出。即指定目的文件。< of=output file > |
ibs=bytes | 一次读入bytes个字节,即指定一个块大小为bytes个字节 |
obs=bytes | 一次输出bytes个字节,即指定一个块大小为bytes个字节 |
bs=bytes | 同时设置读入/输出的块大小为bytes个字节 |
cbs=bytes | 一次转换bytes个字节,即指定转换缓冲区大小 |
skip=blocks | 从输入文件开头跳过blocks个块后再开始复制 |
seek=blocks | 从输出文件开头跳过blocks个块后再开始复制 |
status=progress | 显示进度信息,例如每秒钟复制的字节数和进度百分比等 |
dd命令的基本用法
将一个文件复制到另一个文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | [root@DeveCode mytest]# cat input.txt aaa bbb ccc [root@DeveCode mytest]# ll 总用量 4 -rw-r--r-- 1 root root 12 5月 25 15:19 input.txt [root@DeveCode mytest]# dd if=input.txt of=output.txt bs=1024 记录了0+1 的读入 记录了0+1 的写出 12字节(12 B)已复制,0.000642631 秒,18.7 kB/秒 [root@DeveCode mytest]# ll 总用量 8 -rw-r--r-- 1 root root 12 5月 25 15:19 input.txt -rw-r--r-- 1 root root 12 5月 25 15:20 output.txt [root@DeveCode mytest]# cat output.txt aaa bbb ccc [root@DeveCode mytest]# |
【解释】:将input.txt
文件复制到output.txt
文件中,块大小为1024
字节。
将一个磁盘的内容复制到另一个磁盘中
1 | dd if=/dev/sda of=/dev/sdb bs=4096 |
【解释】:将/dev/sda
磁盘的内容复制到/dev/sdb
磁盘中,块大小为4096
字节。
将一个磁盘的内容复制到一个文件中
1 | dd if=/dev/sda of=image.img bs=4096 count=1000 status=progress |
【解释】:将/dev/sda
磁盘的前1000
个块复制到image.img
文件中,块大小为4096
字节,并显示进度信息。
dd命令高级用法
除了基本的复制和转换操作,dd
命令还有一些高级用法:
使用dd命令创建一个空文件
1 | dd if=/dev/zero of=newfile bs=1M count=10 |
【解释】:创建一个名为newfile的文件,大小为10MB,其中每个块的大小为1MB。
5.2.2使用dd命令进行磁盘克隆
1 | dd if=/dev/sda of=/dev/sdb bs=4096 conv=noerror,sync |
【解释】:将/dev/sda
磁盘的内容复制到/dev/sdb
磁盘中,块大小为4096
字节。conv=noerror,sync
表示在复制过程中忽略读取错误,并将输出同步到磁盘中。
使用dd命令进行数据恢复
1 | dd if=/dev/sda1 of=/mnt/usbdrive/recovered_data.img bs=4096 conv=noerror,sync |
【解释】:将/dev/sda1
分区的内容复制到/mnt/usbdrive/recovered_data.img
文件中,块大小为4096
字节。conv=noerror,sync
表示在复制过程中忽略读取错误,并将输出同步到磁盘中。
使用dd命令进行密码破解
1 | dd if=/dev/sda | john --stdin |
【解释】:将/dev/sda
磁盘的内容传递给john
密码破解工具,用于破解磁盘中的密码。
dd测试IO
dd测试DirectIO
iops——写测试 dd if=/dev/zero of=./a.dat bs=8k count=1M oflag=direct
iops——读测试 dd if=./a.dat of=/dev/null bs=8k count=1M iflag=direct
bw——写测试 dd if=/dev/zero of=./a.dat bs=1M count=8k oflag=direct
bw——读测试 dd if=./a.dat of=/dev/null bs=1M count=8k iflag=direct
dd测试BufferIO
BufferIO主要出现在一些大文件读写的场景,由于使用内存做Cache所以读写性能上和DirectIO相比,通常会高很多,尤其是读,所以这个场景下我们仅关心bw即可。
用dd测试BufferIO的写时,需要增加一个conv=fdatasync,使用该参数,在完成所有读写后会调用一个sync确保数据全部刷到磁盘上(期间操作系统也有可能会主动flush),否则就是主要在测内存读写了;
另外还有一个参数是oflag=dsync,使用该参数也是走的BufferIO,但却是会在每次IO操作后都执行一个sync。
通常conv=fdatasync更符合大文件读写的场景,所以这里以其作为参数进行测试。
bw——写测试 dd if=/dev/zero of=./a.dat bs=1M count=8k conv=fdatasync
bw——读测试 dd if=./a.dat of=/dev/null bs=1M count=8k
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | -- 1) 测试纯写入性能——相当于不写缓存,直接写裸磁盘(写1G文件),每个块8k,总共写128000个块 time dd if=/dev/zero of=output.file bs=8k count=128000 oflag=direct,nonblock -- 2)测试纯读取性能——相当于不读缓存,直接读裸磁盘 dd if=output.file of=/dev/null bs=8k count=128000 iflag=direct,nonblock -- 3)测试同步写入的性能——一次写一个bs大小的数据,同步写到磁盘后再继续写下一个IO,这里每次也是写了缓存,但要等缓存同步到磁盘后才能继续下一个IO dd if=/dev/zero of=/tmp/1G.file bs=4k count=256000 oflag=dsyncdd if=/dev/zero of=/tmp/1G.file bs=4k count=256000 oflag=sync -- 4) 测试同步读取的性能 dd if=/tmp/1G.file of=/dev/null bs=4k count=256000 iflag=dsyncdd if=/tmp/1G.file of=/dev/null bs=4k count=256000 iflag=sync -- 5)测试先写缓存,但最后一次刷新到磁盘中 dd if=/dev/zero of=/tmp/1G.file bs=4k count=256000 conv=fsync dd if=/dev/zero of=/tmp/1G .file bs=4k count=256000 conv=fdatasync -- 6)测试磁盘写能力——默认文件系统 会写缓存,同文件系统决定何时同步至磁盘,写速度一般较快 time dd if=/dev/zero of=output.file bs=8k count=128000 -- 7) 测试磁盘读能力——默认文件系统 会读缓存,读速度一般较快,如果缓存里没有,则也是直接读磁盘,但第2次之前就比较快 time dd if=output.file of=/dev/null bs=8k count=128000 |
dd纯写速度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | [root@s2ahumysqlpg01 fio-3.29]# time dd if=/dev/zero of=/tmp/ddout bs=8k count=5000 5000+0 records in 5000+0 records out 40960000 bytes (41 MB) copied, 0.055353 s, 740 MB/s real 0m0.288s user 0m0.004s sys 0m0.276s [root@s2ahumysqlpg01 fio-3.29]# time dd if=/dev/zero of=/tmp/ddout bs=8k count=50000 50000+0 records in 50000+0 records out 409600000 bytes (410 MB) copied, 1.59508 s, 257 MB/s real 0m1.604s user 0m0.021s sys 0m0.379s [root@s2ahumysqlpg01 fio-3.29]# time dd if=/dev/zero of=/tmp/ddout bs=8k count=500000 500000+0 records in 500000+0 records out 4096000000 bytes (4.1 GB) copied, 40.5061 s, 101 MB/s real 0m40.584s user 0m0.279s sys 0m4.036s |
dd 测试读写速度,就是读当前磁盘文件,再写入当前磁盘之中。一定程度上,复制量越大,读写的时间越长,统计的结果越准。但是测试结果信息量较少,只能作为参考量,更多读写模式和测试信息:可以使用dd 命令参数来配置:
使用conv, iflag, oflag 三个变量可以配置dd 命令的复制模块式,读取模式和写入模式;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #CONV 选项有: ascii 从 EBCDIC 到 ASCII ebcdic 从 ASCII 到 EBCDIC ibm 从 ASCII 到备用 EBCDIC block 用空格填充换行符终止的记录到 cbs-size unblock 用换行符替换 cbs-size 记录中的尾随空格 lcase 将大写改为小写 ucase 将小写变为大写 sparse 尝试寻找而不是写入 NUL 输入块的输出 swab 交换每对输入字节 sync 用 NUL 填充每个输入块到 ibs 大小; 与 block 或 unblock 一起使用时,用空格而不是 NUL 填充 excl 如果输出文件已经存在,则失败 nocreat 不创建输出文件 notrunc 不截断输出文件 noerror 在读取错误后继续 fdatasync 在完成之前物理写入输出文件数据 fsync 同样,还要写入元数据 #FLAG( iflag, oflag) 选项有: append 附加模式(仅对输出有意义;建议使用 conv=notrunc) direct 对数据使用直接 I/O directory 除非目录失败 dsync 对数据使用同步 I/O sync 同样,也适用于元数据 fullblock 累积输入的完整块(仅 iflag) nonblock 使用非阻塞 I/O noatime 不更新访问时间 nocache 丢弃缓存数据 noctty 不从文件中分配控制终端 nofollow 不遵循符号链接 count_bytes 将 'count=N' 视为字节数(仅限 iflag) skip_bytes 将 'skip=N' 视为字节数(仅 iflag) seek_bytes 将 'seek=N' 视为字节数(仅用于标记) #如果要规避掉文件系统cache,直接读写,不使用buffer cache,需做这样的设置 iflag=direct,nonblock oflag=direct,nonblock |
dd纯读速度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | [root@s2ahumysqlpg01 fio-3.29]# time dd if=/tmp/ddout of=/dev/null bs=4k count=5000 5000+0 records in 5000+0 records out 20480000 bytes (20 MB) copied, 0.180166 s, 114 MB/s real 0m0.198s user 0m0.000s sys 0m0.033s [root@s2ahumysqlpg01 fio-3.29]# time dd if=/tmp/ddout of=/dev/null bs=4k count=50000 50000+0 records in 50000+0 records out 204800000 bytes (205 MB) copied, 1.5581 s, 131 MB/s real 0m1.560s user 0m0.026s sys 0m0.271s [root@s2ahumysqlpg01 fio-3.29]# time dd if=/tmp/ddout of=/dev/null bs=4k count=500000 500000+0 records in 500000+0 records out 2048000000 bytes (2.0 GB) copied, 18.0358 s, 114 MB/s real 0m18.038s user 0m0.240s sys 0m2.054s |
dd 命令三种经典测试
1 2 3 4 5 6 7 8 9 10 11 | # dd 命令三种经典使用方法: dd if=/dev/zero of=test bs=64k count=16k 是不准确的,可能有数据存在内核缓存中,没有同步到磁盘上。对于关键数据应该加上fsync标识,防止关键数据丢失; dd if=/dev/zero of=test bs=64k count=16k conv=fsync 较为稳妥,但是时间用时较长,他在dd结束前会写数据和文件元数据到磁盘; dd if=/dev/zero of=test bs=64k count=4k oflag=dsync or sync 每写一次就写一次磁盘,在实际操作中,可以听到磁盘响声,用时较长; #SSD 性能测试: PCIe-SSD Optane: dd if=/dev/urandom of=./optane.bin bs=256k count=102400 (顺序写 25GB的随机数据) M.2-STAT-SSD: dd if=/dev/urandom of=./m2sata.bin bs=256k count=102400 (顺序写 25GB的随机数据) M.2-NVMe-SSD: dd if=/dev/urandom of=./m2nvme.bin bs=256k count=102400 (顺序写 25GB的随机数据) HDD: dd if=/dev/urandom of=./sata.bin bs=256k count=102400 (顺序写 25GB的随机数据) |
其它dd介绍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 | dd指令使用 语法格式 dd [option] 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=ASCII:把EBCDIC码转换为ASCIl码。 conv=ebcdic:把ASCIl码转换为EBCDIC码。 conv=ibm:把ASCIl码转换为alternate EBCDIC码。 conv=block:把变动位转换成固定字符。 conv=ublock:把固定位转换成变动位。 conv=ucase:把字母由小写转换为大写。 conv=lcase:把字母由大写转换为小写。 conv=notrunc:不截短输出文件。 conv=swab:交换每一对输入字节。 conv=noerror:出错时不停止处理。 conv=sync:把每个输入记录的大小都调到ibs的大小(用NUL填充)。 注意:指定数字的地方若以下列字符结尾乘以相应的数字:b=512, c=1, k=1024, w=2, xm=number m,kB=1000,K=1024,MB=1000*1000,M=1024*1024,GB=1000*1000*1000,G=1024*1024*1024 dd使用实例 假设了如下的情况: 要备份的数据文件:30720KB block 0 =8 KB. raw offset 64 KB. 设定 bs=8k 1、从raw设备备份到raw设备 dd if=/dev/rsd1b of=/dev/rsd2b bs=8k skip=8 seek=8 count=3841 2、裸设备到文件系统 dd if=/dev/rsd1b of=/backup/df1.dbf bs=8k skip=8 count=3841 3、文件系统到裸设备 dd if=/backup/df1.dbf of=/dev/rsd2b bs=8k seek=8 4、文件系统到文件系统,你可以为了提升I/O把bs设为较高的数值 dd if=/oracle/dbs/df1.dbf of=/backup/df1.dbf bs=1024k 5、备份/dev/hdx全盘数据,并利用gzip工具进行压缩,保存到指定路径(bzip2工具也一样可使用) dd if=/dev/hdx | gzip > /path/to/image.gz 6、生成1G的虚拟块设备Sparse File(稀疏文件) dd if=/dev/zero of=1G.img bs=1M seek=1000 count=0 Sparse File是什么,稀疏文件,也就是说,是一个拥有空的空间的文件,磁盘块将并没分配给这些文件。如果这些空的空间填满ASCII的NULL字符,那么文件才会是实际的大小。 7、拷贝光盘数据到backup文件夹下,并保存为cd.iso文件,再进行刻录 dd if=/dev/cdrom of=/backup/cd.iso cdrecord -v cd.iso 8、将内存里的数据拷贝到backup目录下的mem.bin文件 dd if=/dev/mem of=/backup/mem.bin bs=1024 9、将软驱数据备份到当前目录的disk.img文件 dd if=/dev/fd0 of=disk.img count=1 bs=1440k 10、将备份文件恢复到指定盘 dd if=/backup/df1.dbf of=/dev/rsd1b 11、将压缩的备份文件恢复到指定盘 gzip -dc /path/to/image.gz | dd of=/dev/hdx 12、测试磁盘写能力 time dd if=/dev/zero of=/test.dbf bs=8k count=300000 因为/dev/zero是一个伪设备,它只产生空字符流,对它不会产生IO,所以,IO都会集中在of文件中,of文件只用于写,所以这个命令相当于测试磁盘的写能力。 13、测试磁盘读能力 time dd if=/dev/sdb1 of=/dev/null bs=8k 因为/dev/sdb1是一个物理分区,对它的读取会产生IO,/dev/null是伪设备,相当于黑洞,of到该设备不会产生IO,所以,这个命令的IO只发生在/dev/sdb1上,也相当于测试磁盘的读能力。 14、测试同时读写能力 time dd if=/dev/sdb1 of=/test1.dbf bs=8k 这个命令下,一个是物理分区,一个是实际的文件,对它们的读写都会产生IO(对/dev/sdb1是读,对/test1.dbf是写),假设他们都在一个磁盘中,这个命令就相当于测试磁盘的同时读写能力 15、备份磁盘开始的512Byte大小的MBR信息到指定文件 dd if=/dev/hdx of=/path/to/image count=1 bs=512 16、恢复MBR dd if=/mnt/windows/linux.lnx of=/dev/hda bs=512 count=1 17、 得到最恰当的block size。 通过比较dd指令输出中所显示的命令执行时间(选时间最少的那个),即可确定系统最佳的block size大小 dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file dd if=/dev/zero bs=2048 count=500000 of=/root/1Gb.file dd if=/dev/zero bs=4096 count=250000 of=/root/1Gb.file dd if=/dev/zero bs=8192 count=125000 of=/root/1Gb.file Oracle数据库的dd备份 说明,以下实验操作系统版本为RHEL 5.4没有offset Raw offset 在一些os上,在裸设备上的文件的开头是被os使用的。这些存储空间被叫做raw offset,Oracle不会备份和恢复这些内容(字节)。因此,备份的时候要跳过含有offset的字节。 目前只有AIX和Tru64系统的裸设备存在offset,详细信息如下 UNIX OS Reserved Size ------------ ---------------- SUN Solaris 0 HP-UX 0 IBM AIX 4k Tru64 UNIX 64k Linux 0 在 Aix环境中,如果是使用了原始VG,或者是Big VG,但是创建LV的时候没有指定-T O标签,创建出来的LV都带有4K保留空间,如果把这些LV作为裸设备使用,则需要注意这个4K的问题。如果是使用了Scalable-type VG,或者是使用Big VG,而且在创建VG的时候使用了-T O标签,则创建的LV没有4K保留空间,称为DS_LVZ类型的LV。 在AIX平台下,我们可以使用$ORACLE_HOME/bin路径下的dbfsize命令确认裸设备是否包含offset 下面是包含offset的裸设备 #dbfsize /dev/rlv_data01_10g Database file: /dev/rlv_data01_10g Database file type:raw device Database file size: 1048448 8192 byte blocks 下面是不包含offset的裸设备 #dbfsize /dev/rlv_data01_10g Database file: /dev/rlv_data01_10g Database file type:raw device without 4K starting offset Database file size: 1048448 8192 byte blocks block 0 在 每个oracle文件的开头,os系统放置了一个块叫做block 0。 这个块的大小和其所在数据文件的oracle块大小相同。 一般的oracle 代码不能识别这个块,但是这个块是包含在os上的文件大小里面的。就是说oracle认为datafile1大小为100块,但是os看来,datafile1大小为101块(100+block 0). 注意,利用dd备份时,需要包含block 0。因为block 0位于offset之后,而block 0是所有数据文件都需要的,无论它是基于裸备还是文件系统,且block 0的大小只与oracle的block size有关,所以,把block 0也dd出来是必要的,不需要skip数据文件的block 0。 计算数据文件的占用的实际空间大小 实际的数据文件大小是在dba_data_files中的bytes + 1* blocksize SQL> select file_name,bytes from dba_data_files; FILE_NAME BYTES BLOCKSIZE ---------------------------------------- ---------- ---------- /opt/oracle/oradata/test1/system01.dbf 360710144 8192 在操作系统查看文件大小: # ls -l system01.dbf -rw-r--r-- 1 oracle oinstall 360718336 Nov 15 11:53 system01.dbf 360718336 = 360710144 + 8192 (8192是数据文件所在表空间的blocksize) 那么一个裸设备的数据文件最多可以是多大? 这个和具体的操作系统和数据文件所在表空间的blocksize有关。 假设裸设备的大小是r,操作系统裸设备的offset为f,数据文件所在表空间的blocksize是b,则数据文件的最大大小为: d=r – f – b*1 (1为block 0) 如裸设备大小为1008k,offset为0,表空间的blocksize为4k,则在此裸设备的数据文件的最大大小为: d=1008-0-1*4=1004(k) 实例测试 从裸设备到裸设备拷贝ORACLE数据文件 1、创建裸设备 # fdisk /dev/sdd The number of cylinders for this disk is set to 25856. There is nothing wrong with that, but this is larger than 1024, and could in certain setups cause problems with: 1) software that runs at boot time (e.g., old versions of LILO) 2) booting and partitioning software from other OSs (e.g., DOS FDISK, OS/2 FDISK) Command (m for help): n Command action l logical (5 or over) p primary partition (1-4) l First cylinder (4201-4485, default 4201): Using default value 4201 Last cylinder or +size or +sizeM or +sizeK (4201-4485, default 4485): +10M Command (m for help): n Command action l logical (5 or over) p primary partition (1-4) l First cylinder (4212-4485, default 4212): Using default value 4212 Last cylinder or +size or +sizeM or +sizeK (4212-4485, default 4485): +20M Command (m for help): n Command action l logical (5 or over) p primary partition (1-4) l First cylinder (4232-4485, default 4232): Using default value 4232 Last cylinder or +size or +sizeM or +sizeK (4232-4485, default 4485): +30M Command (m for help): n Command action l logical (5 or over) p primary partition (1-4) l First cylinder (4262-4485, default 4262): Using default value 4262 Last cylinder or +size or +sizeM or +sizeK (4262-4485, default 4485): +40M Command (m for help): p Disk /dev/sdd: 27.1 GB, 27111981056 bytes 64 heads, 32 sectors/track, 25856 cylinders Units = cylinders of 2048 * 512 = 1048576 bytes Device Boot Start End Blocks Id System /dev/sdd1 1 3816 3907568 83 Linux /dev/sdd4 3817 4485 685056 5 Extended /dev/sdd5 3817 3912 98288 83 Linux /dev/sdd6 3913 4008 98288 83 Linux /dev/sdd7 4009 4104 98288 83 Linux /dev/sdd8 4105 4200 98288 83 Linux /dev/sdd9 4201 4211 11248 83 Linux /dev/sdd10 4212 4231 20464 83 Linux /dev/sdd11 4232 4261 30704 83 Linux /dev/sdd12 4262 4300 39920 83 Linux Command (m for help): w The partition table has been altered! Calling ioctl() to re-read partition table. The new table will be used at the next reboot. Syncing disks. # partprobe # raw /dev/raw/raw3 /dev/sdd9 /dev/raw/raw3: bound to major 8, minor 57 # raw /dev/raw/raw4 /dev/sdd10 /dev/raw/raw4: bound to major 8, minor 58 # raw /dev/raw/raw5 /dev/sdd11 /dev/raw/raw5: bound to major 8, minor 59 # raw /dev/raw/raw6 /dev/sdd12 /dev/raw/raw6: bound to major 8, minor 60 2、基于裸设备创建表空间 SQL>create tablespace mytest datafile '/dev/raw/raw3' size 5m,'/dev/raw/raw6' size 10m; Tablespace created. 3、从小裸设备到大裸设备 # dd if='/dev/raw/raw3' of='/dev/raw/raw4' 22496+0 records in 22496+0 records out 11517952 bytes (12 MB) copied, 104.599 seconds, 110 kB/s 4、从大裸设备到小裸设备,但数据文件比小裸设备小 # dd if='/dev/raw/raw6' of='/dev/raw/raw5' bs=1024k count=12 12+0 records in 12+0 records out 12582912 bytes (13 MB) copied, 3.34273 seconds, 3.8 MB/s 注意:这里bs*count要大于原裸设备上的数据文件尺寸 5、重启数据库至mount状态 SQL> shutdown immediate; Database closed. Database dismounted. ORACLE instance shut down. SQL> startup mount; ORACLE instance started. Total System Global Area 369098752 bytes Fixed Size 1219472 bytes Variable Size 125830256 bytes Database Buffers 239075328 bytes Redo Buffers 2973696 bytes Database mounted. 6、重命名数据文件,并打开数据库 SQL> alter database rename file '/dev/raw/raw3' to '/dev/raw/raw4'; Database altered. SQL> alter database rename file '/dev/raw/raw6' to '/dev/raw/raw5'; Database altered. SQL> alter database open; Database altered. 从这个测试可以看出: 1、从小裸设备到大裸设备,只需把小裸设备的所有数据块dd到大裸设备即可 2、 是否可以把大裸设备上的数据文件dd到小裸设备,取决于位于大裸设备上的数据文件尺寸(+block 0)是否比小裸设备小。如果数据文件小于小裸设备,则可以把数据文件从大裸设备dd到小裸设备上,在dd过程中不需要太准确计算原来数据文件的大小,只要 保证dd的总量大于数据文件并小于小裸设备的尺寸即可。 3、如果数据文件大于小裸设备的尺寸,则肯定不能把它从大裸设备拷贝到小裸设备上 4、 裸设备之间拷贝数据文件比裸设备到文件系统之间拷贝的优点在于:不需要精确计算要拷贝多少数据,只需要保证覆盖了数据文件+block 0即可;而从裸设备到文件系统拷贝数据文件时,必须准确计算出要拷贝的数据量(数据文件+block 0),dd多一点或者少一点都会报错。 5、 如果有offset的话,在裸设备之间拷贝数据文件的时候都要考虑(skip、seek) 从文件系统到裸设备拷贝ORACLE数据文件 继续上面的实验,首先要保证裸设备的大小要大于等于oracle数据文件大小+ block 0,如果裸设备需要offset的话,则要保证更大,然后直接用dd就可以。 1、创建表空间,数据文件大小为5m SQL> create tablespace mytest1 datafile '/home/oracle/mytest1.dbf' size 5m; Tablespace created. # ls -l /home/oracle/mytest1.dbf -rw-r----- 1 oracle oinstall 5251072 Dec 16 21:37 /home/oracle/mytest1.dbf 2、dd文件到裸设备上 # dd if='/dev/zero' of='/dev/raw/raw3' bs=1024k dd: writing `/dev/raw/raw3': No space left on device 11+0 records in 10+0 records out 11517952 bytes (12 MB) copied, 7.63555 seconds, 1.5 MB/s # dd if=/home/oracle/mytest1.dbf of=/dev/raw/raw3 10256+0 records in 10256+0 records out 5251072 bytes (5.3 MB) copied, 35.9816 seconds, 146 kB/s 注意:从文件系统到裸设备不用设置count 3、重命名数据文件,打开数据库 SQL> alter database rename file '/home/oracle/mytest1.dbf' to '/dev/raw/raw3'; Database altered. SQL> alter database open; Database altered 从裸设备到文件系统拷贝ORACLE数据文件 这里不并不是所有情况都能把整个裸设备拷贝到文件中,要看裸设备是否有offset,如果有offset,则肯定不能全拷贝出来,需要使用skip参数跳过offset,以下演示没有offset的情况 1、在mytest1表空间上创建表,并填充数据,然后将整个裸设备备份到文件系统 SQL> create table test tablespace mytest1 2 as 3 select * from dba_users; Table created. #dd if='/dev/raw/raw3' of='/home/oracle/mytest2.dbf' bs=512k 21+1 records in 21+1 records out 11517952 bytes (12 MB) copied, 0.804403 seconds, 14.3 MB/s 2、重启数据库,并充命名数据文件 SQL> shutdown immediate; Database closed. Database dismounted. ORACLE instance shut down. SQL> startup mount; ORACLE instance started. Total System Global Area 369098752 bytes Fixed Size 1219472 bytes Variable Size 134218864 bytes Database Buffers 230686720 bytes Redo Buffers 2973696 bytes Database mounted. SQL> alter database rename file '/dev/raw/raw3' to '/home/oracle/mytest2.dbf'; Database altered. SQL> alter database open; alter database open * ERROR at line 1: ORA-01113: file 9 needs media recovery ORA-01110: data file 9: '/home/oracle/mytest2.dbf' 可以看到数据库无法打开,这是因为裸设备已被数据文件使用部分的逻辑块与未使用部分的逻辑块大小不一致。这种情况下,只能拷贝裸设备中数据文件大小 + block 0部分。这里用到两个工具 dbfsize 求出在裸设备或者文件系统上的oracle数据文件的大小,由oracle提供。 blockdev 求出裸设备的大小,操作系统自带。 要计算出要要拷贝的大小,否则报错,如: $ dbfsize /dev/raw/raw3 Database file: /dev/raw/raw3 Database file type: raw device Database file size: 640 8192 byte blocks $ blockdev --getsize /dev/raw/raw3 22496 一般一个OS BLOCK大小是512字节,所以22496*512/1024/1024= 10.9(m) 就是裸设备的大小。 $ rm /home/oracle/mytest2.dbf $ dd if='/dev/raw/raw3' of='/home/oracle/mytest2.dbf' bs=8k count=641 SQL> alter database open; Database altered |
dd命令的替代工具
除了dd
命令,Linux
系统中还有一些其他的命令和工具可以用于复制和转换操作,例如cp
、rsync
、tar
、ddrescue
等。
cp
命令:用于复制文件和目录,可以在不同的目录之间复制文件和目录。rsync
命令:用于远程数据同步,可以在本地和远程系统之间同步文件和目录。tar
命令:用于打包和解压文件,可以将多个文件和目录打包成一个文件,并进行解压操作。ddrescue
命令:用于数据恢复,可以在损坏的磁盘上执行数据恢复操作。
这些命令和工具都有各自的优缺点,需要根据具体情况选择合适的工具。例如,如果需要复制文件或目录,可以使用cp
命令;如果需要进行远程数据同步,可以使用rsync
命令;如果需要进行数据恢复,可以使用ddrescue
命令。
dd命令的常见问题
dd命令执行后没有输出?
dd
命令执行时,通常不会有输出。如果需要查看操作进度,可以使用status=progress
选项,例如:
1 | dd if=/dev/sda of=/dev/sdb status=progress |
dd命令执行过程中出现错误?
dd
命令执行时,可能会出现错误。常见的错误包括磁盘读取错误、磁盘空间不足等。如果出现错误,可以尝试使用conv=noerror
选项忽略错误,或者使用其他工具进行数据恢复。
dd命令执行后磁盘容量变小了?
dd
命令执行时,可能会出现磁盘容量变小的情况。
这是因为dd
命令会忽略磁盘末尾的空白区域。如果需要复制整个磁盘,可以使用conv=sync,noerror
选项,例如:dd if=/dev/sda of=/dev/sdb conv=sync,noerror
dd命令可以用于病毒清除吗?
dd
命令不是专门用于病毒清除的工具,但可以用于清除病毒。
如果系统感染了病毒,可以使用dd
命令清除感染的磁盘分区或整个磁盘。但需要注意的是,清除病毒会导致数据丢失,因此需要提前备份重要数据。
总结
磁盘IO测试工具有fio、dd、sysbench、GreenPlum提供的gpcheckperf工具、iometer 、 Orion等。