在UNIX裸设备与文件系统间移动Oracle

一、裸设备的相关问题 1.1 裸设备(RAW DEVICE)是什么? 裸设备是指未创建文件系统的磁盘分区(raw partition)或逻辑卷(raw logical volume) , 应用程序直接通过一 个字符设备驱动程序对它进行访问 。如何对设备上的数据读写决定于使用它的应用程序 。由于对裸设备的操作不通过UNIX的缓冲区 , 数据在ORACLE的数据缓冲区(BUFFER CACHE)和磁盘之间直接传递 , 所以使用裸设备在一定程度上能够提高I/O性能 , 适合I/O量大的系统 。另外OPS/RAC (Oracle Parallel Server/Real Application Cluster)环境下 , 多个节点同时访问同一个数据库 , 所以CONTROL FILE、DATA FILE、REDO LOG都必须建在RAW DEVICE上 。1.2 裸设备的可用空间 不同的UNIX对裸设备的管理不完全相同 , 特别要注意的是某些UNIX在每个裸设备的头部要保留一定的空间 , 应用程序在使用裸设备时不可以覆盖这一部分 , 否则会对裸设备造成损坏 。所以一个裸设备的实际可用空间是分配给裸设备的空间再减去这部分操作系统保留空间 。下面是常用UNIX的OS Reserved Size列表: UNIXOS Reserved Size ---------------------------- SUN Solaris0 HP-UX0 IBM AIX4k Tru64 UNIX64k Linux0 1.3 dd命令 UNIX上读写裸设备不能使用cp, cpio, tar等命令 , 必须用dd , 下面是几个dd常用参数的简单说明 , 更详细的信息请参考UNIX使用手册或用命令man dd 。dd [ operand=value ... ] if=file 指定输入文件 , 缺省值是标准输入 of=file 指定输出文件 , 缺省值是标准输出 bs=n 设置输入和输出的块大小为n字节 , 也可以用“k”作单位 skip=n 在拷贝之前跳过n个输入块 , 缺省值是0 seek=n 在拷贝之前从输出文件首部跳过n块 , 缺省值是0 count=n 指定拷贝的块数 , 缺省拷贝到输入文件结束 1.4 本文中相关示例的说明 a. 所有例子中ORACLE的DB_BLOCK_SIZE都是8k b. /oradata是一文件系统目录 c. /dev/rlv_data , /dev/rlv_redo和/dev/rlv_ctrl是三个RAW DEVICE , 大小均为8MB(8192k) d. 在未提到操作系统时 , 默认是AIX , OS_RESERVED_SIZE=4K
二、移动数据文件(DATAFILE) 2.1 在裸设备上建立数据文件 用以下命令建立表空间: SQL> CREATE TABLESPACE ts_test DATAFILE "/dev/rlv_data" SIZE 8180k; SIZE指定的数值必须小于或等于8180k , 否则语句将会失败: ORA-01119: error in creating database file "/dev/rlv_data" ORA-27042: not enough space on raw partition to fullfill request 这个最大值的计算方法如下: 8192k(RAW DEVICE SIZE) - 4k (OS_RESERVED_SIZE) - 8k (DB_BLOCK_SIZE) = 8180k 为什么还要减去一个DB_BLOCK_SIZE呢?这是因为ORACLE建立DATAFILE时 , 在命令中SIZE指定的大小之外 , 还要在文件头另加一个BLOCK , 叫作“Oracle OS Header Block” , 里面保存有这个文件的逻辑块大小和文件块数等信息 。这一点并不是在RAW DEVICE上建DATAFILE特有的 , 如果你在文件系统上建一个DATAFILE , 指定SIZE 1000k的话 , 你用ls -l或dir命令看到的文件大小将是1008k (DB_BLOCK_SIZE=8K) 。2.2 在文件系统和裸设备之间移动数据文件 2.2.1 从文件系统到裸设备 a. 在文件系统上建一个4M的DATAFILE SQL> CREATE TABLESPACE test DATAFILE "/oradata/test.dbf" SIZE 4M; b. 查看一下这个新建的DATAFILE的大小 (注:4202496 = 4M8K) $ ls -l /oradata/test.dbf -rw-r----- 1 oracle dba 4202496 Aug 29 15:01 /oradata/test.dbf c. 按下表公式确定dd的参数 d. 在数据库没有OPEN的状态下 , 用dd进行拷贝 , 下面给出命令及输出 AIX$ dd if=/oradata/test.dbf of=/dev/rlv_data bs=4k seek=1 1026 0 records in 1026 0 records out Tru64$ dd if=/oradata/test.dbf of=/dev/rlv_data bs=64k seek=1 64 1 records in 64 1 records out Other$ dd if=/oradata/test.dbf of=/dev/rlv_data bs=1024k 4 1 records in 4 1 records out 2.2.2 从裸设备到文件系统 a. 确定数据文件实际大小file_size , 用于下一步计算dd的参数count 。如果count计算不对 , 拷贝出的数据文件无效 , 数据库无法打开 。SQL> SELECT bytes, blocks, bytes/blocks db_block_size, bytes bytes/blocks file_size FROM dba_data_files WHERE file_name="/dev/rlv_data"; BYTESBLOCKSDB_BLOCK_SIZEFILE_SIZE ---------- -------- ------------- --------- 419430451281924202496 b. 按下表公式确定dd的参数 , min表示二者之中取较小的 c. 在数据库没有OPEN的状态下 , 用dd进行拷贝 , 下面给出命令及输出 AIX$ dd if=/dev/rlv_data of=/oradata/test2.dbf bs=4k skip=1 count=1026 1026 0 records in 1026 0 records out Tru64$ dd if=/dev/rlv_data of=/oradata/test2.dbf bs=8k skip=8 count=513 513 0 records in 513 0 records out Other$ dd if=/dev/rlv_data of=/oradata/test2.dbf bs=8k count=513 513 0 records in 513 0 records out

推荐阅读