Linux 上的裸设备

什么是裸设备?

裸设备,也称为裸分区,是一个未被挂载且不由Linux文件系统(如ext2/ext3、reiserfs)或Oracle集群文件系统(OCFS、OCFS2)写入的磁盘分区,而是通过字符设备驱动程序直接访问。应用程序负责组织数据如何写入磁盘分区的细节。

如何识别裸设备?

所有硬件设备看起来都像是常规文件;它们可以使用与操作文件相同的、标准的系统调用来打开、关闭、读取和写入。系统中的每个设备都由一个设备特殊文件表示,例如系统中的第一个IDE磁盘由/dev/hda表示。对于块(磁盘)和字符设备,这些设备特殊文件是由mknod命令创建的,它们使用主设备号和次设备号来描述设备。

由同一个设备驱动程序控制的所有设备都有一个共同的主设备号。 次设备号用于区分不同的设备及其控制器,例如主IDE磁盘上的每个分区都有一个不同的次设备号。所以,/dev/hda2,即主IDE磁盘的第二个分区,其主设备号为3,次设备号为2。Linux通过主设备号和一些系统表(例如字符设备表,chrdevs)将系统调用中传递的设备特殊文件映射到设备的设备驱动程序。

Linux支持三种类型的硬件设备:字符设备、块设备和网络设备。

字符设备是直接读写而不经过缓冲的。
块设备只能以块大小的倍数进行读写,通常是512或1024字节。块设备通过缓冲区缓存访问,并且可以随机访问,也就是说,可以读取或写入设备上的任何块,无论它位于何处。块设备可以通过它们的设备特殊文件访问,但更常见的是通过文件系统访问。只有块设备可以支持挂载的文件系统。
网络设备通过BSD套接字接口和网络章节中描述的网络子系统访问。
裸设备是字符设备(主设备号为162)。 第一个次设备号(即0)被保留作为控制接口,通常可以在/dev/rawctl找到。 以下是一系列列出裸设备的命令:

1
2
3
4
5
6
7
8
9
# ls -lR /dev/rawctl
crw-rw---- 1 root disk 162, 0 Mar 19 2002 /dev/rawctl

# ls -lR /dev/raw[1-4]
crw-rw---- 1 root disk 162, 1 Mar 19 2002 /dev/raw1
crw-rw---- 1 root disk 162, 2 Mar 19 2002 /dev/raw2
crw-rw---- 1 root disk 162, 3 Mar 19 2002 /dev/raw3
crw-rw---- 1 root disk 162, 4 Mar 19 2002 /dev/raw4

裸设备的好处是什么?

裸设备可以绑定到一个现有的块设备(例如,一个磁盘)上,并用于对该现有块设备执行“原始”IO操作。 这种“原始”IO绕过了通常与块设备关联的缓存(Linux缓冲区缓存)并消除了文件系统开销,如索引节点或空闲列表。因此,裸设备提供了一个更“直接”的路径到物理设备,并允许应用程序对物理设备的IO操作时机有更多的控制。这使得裸设备适合于数据库管理系统等复杂应用程序,这些应用程序通常执行自己的缓存。

如果没有I/O瓶颈,裸设备将不会有所帮助。请注意,总的I/O量并没有减少;只是执行得更加高效。

是否存在必须使用裸设备的情况?

如果您在使用Oracle并行服务器(OPS)或Oracle实时应用集群(RAC)且没有使用Oracle集群文件系统(OCFS),那么所有数据文件、控制文件和重做日志文件必须放置在裸分区上,以便它们可以在节点之间共享。此外,如果您使用列表I/O或异步I/O,这些功能允许程序发出多个写操作,而无需等待前一个写操作的返回,为了利用这一点,数据文件需要位于裸设备上。

我可以将整个裸分区用于Oracle吗?

不可以。您应该指定一个比裸分区大小稍小的表空间,具体来说,至少要比裸分区小两个Oracle块大小。

Linux默认有多少个裸设备,我最多可以使用多少个裸设备?

Linux可以访问的裸设备数量限制为255个。 默认情况下,/dev/raw下有128个裸设备:

1
2
3
4
5
# ls -l /dev/raw*
crw-rw---- 1 root disk 162, 1 Mar 19 2002 /dev/raw1
(...)
crw-rw---- 1 root disk 162, 3 Mar 19 2002 /dev/raw128

Linux无法处理每个驱动器上的过多分区。因此,在Linux中,您有4个主分区(如果您使用逻辑分区,其中3个可用)以及在SCSI磁盘上最多15个分区(在IDE磁盘上最多63个分区)。

根据这段描述,Linux默认情况下提供了128个裸设备,但理论上,您最多可以使用255个裸设备。不过,实际可用的裸设备数量可能会受到系统配置和硬件限制的影响。

如何创建新的裸设备?

如果需要创建其他裸设备,必须以root用户身份执行以下命令(请参阅man mknod):

1
2
3
4
5
6
7
8
9
10
# mknod -m 660 /dev/raw/rawXXX c 162 XXX
# chown root:disk /dev/raw/rawXXX
(where XXX= 128< integer < 256)

i.e.:
# mknod -m 660 /dev/raw/raw130 c 162 130
# chown root:disk /dev/raw/raw130
# ls -l /dev/raw/raw130
crw-rw---- 1 root disk 162, 130 Dec 23 18:57 /dev/raw130

谁应该拥有裸设备?

您需要以root身份创建裸设备,但之后应该将所有权更改为’oracle’账户。组也必须更改为’dba’组(通常称为dba)。

我如何为Oracle RDBMS使用裸设备?

我们假设有一个SCSI磁盘驱动器 - 9GB。步骤如下:
a. 对磁盘驱动器进行分区(/dev/sdb)
b. 将裸设备与新SCSI磁盘上的分区绑定
c. 更改裸设备的所有权
d. 在裸设备上创建新的Oracle数据文件

对磁盘驱动器进行分区,使用fdisk命令(请参阅man fdisk):
以root用户身份,输入以下命令:

1
# fdisk /dev/sdb

输入 ‘p’ 以查看磁盘驱动器上现有分区的列表:

1
2
3
4
command (m for help): p
Disk /dev/sdb: 255 heads, 63 sectors, 1174 cylinders
Units = cylinders of 16065 * 512 bytes

设备 引导 开始 结束 块 ID 系统

3.a. 为了创建一个分区,选择 ‘n’ 命令,然后选择 ‘e’ 选项来创建一个扩展分区。 您需要扩展分区,因为这块磁盘将包含超过4个分区。 首先创建编号为1的分区,因此选择编号1。

1
2
3
4
5
6
7
8
9
10
11
command (m for help): n
command action
e extended
p primary partition (1-4)
e
Partition Number (1-4): 1
First cylinder (1-1115, default 1):
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-1115, default 1115):
Using default value 1115

3.b. 现在在扩展分区内部, 我将不得不创建6个大小相等的逻辑分区:每个应该为257MB大(256MB+1MB用于头部)。 按下 ‘n’ 和 ‘l’ 然后 <回车>,并写入分区的大小(以 + 开头)+257M。 重复这些步骤6次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
command (m for help): n
command action
l logical (5 or over)
p primary partition (1-4)
l
Partition Number (1-4): 1
First cylinder (1-1115, default 1):
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-1115, default 1115): +257M
(...repeat 5 time...)

command (m for help): p
Disk /dev/sdb: 255 heads, 63 sectors, 1174 cylinders
Units = cylinders of 16065 * 512 bytes

Device Boot Start End Block ID System
/dev/sdb1 1 1115 8956206 5 Extended
/dev/sdb5 1 33 265009+ 83 Linux
/dev/sdb6 34 66 265041 83 Linux
(...)
/dev/sdb10 166 198 265041 83 Linux

3.c. 现在,请按 ‘w’,这将把分区表写入磁盘并退出fdisk程序。

将裸设备与新SCSI磁盘上的分区绑定
可以使用一个名为raw的工具(请参阅man raw)来将裸设备绑定到现有的块设备:

1
2
3
4
5
6
# raw /dev/raw/raw1 /dev/sdb5
/dev/raw/raw1: bound to major 8, minor 3
(...)
# raw /dev/raw/raw6 /dev/sdb10
/dev/raw/raw6: bound to major 8, minor 3

关于这一点的最后细节是,裸设备驱动器到分区的分配应该在每次启动后进行。因此,以root用户身份,编辑 /etc/sysconfig/rawdevices 文件,并在其中放入以下裸命令:

1
2
3
4
5
6
7
raw /dev/raw/raw1 /dev/sdb5
raw /dev/raw/raw2 /dev/sdb6
raw /dev/raw/raw3 /dev/sdb7
raw /dev/raw/raw4 /dev/sdb8
raw /dev/raw/raw5 /dev/sdb9
raw /dev/raw/raw6 /dev/sdb10

更改裸设备的所有权
以root用户身份输入以下命令:

1
2
3
# cd /dev/raw
# chown oracle:dba raw[1-4]

在裸设备上创建新的Oracle数据文件
使用裸设备时,您需要用单引号指定完整的路径名,并使用REUSE参数。 在裸分区上创建Oracle表空间时,需要指定比实际分区大小稍小的尺寸。 这个尺寸可以按照以下方式计算:

1
2
3
4
5
6
7
8
9
10
11
Size of Redo Log = Raw Partition Size - 1*512 byte block
Size of Data File = Raw Partition Size - 2* Oracle Block Size

e.g. (db_block_size=8192):
create tablespace tablespace_on_raw datafile '/dev/raw/raw1' size 246784K REUSE,
datafile '/dev/raw/raw2' size 246784K REUSE,
datafile '/dev/raw/raw3' size 246784K REUSE,
datafile '/dev/raw/raw4' size 246784K REUSE,
datafile '/dev/raw/raw5' size 246784K REUSE,
datafile '/dev/raw/raw6' size 246784K REUSE;

Oracle块大小在裸设备上是否有所关联?

它的重要性不如UNIX文件那么大;Oracle块的大小可以更改,但它必须是物理块大小的倍数,因为只能寻址到物理块边界,因此只能以物理块大小的倍数进行写入。

如果我的数据库文件位于裸设备上,我该如何备份它们?

您不能使用诸如 ‘tar’ 或 ‘cpio’ 这样的工具,因为这些工具期望存在文件系统。

通常,人们使用 ‘dd’ 命令将Oracle数据文件从文件系统移动到裸设备。使用 ‘dd’ 是完成这一任务的最快方法。然而,有必要知道在裸设备中要跳过多少块(例如,在Tru64 Unix上,您需要跳过64K),这样您就不会覆盖操作系统所需的信息。如何跳过块的信息在不同的平台上是不同的。在Linux上,您不需要指定跳过位移。使用RMAN时,没有必要知道此类特定于平台的信息。使用RMAN复制命令,可以将数据文件从文件系统文件复制到裸设备。

使用 ‘dd’ 命令的一个示例:

1
# dd if=/dev/raw/raw1 of=/u01/oradata/test_ts.dbf' bs=16K

保持块大小为Oracle块大小的倍数。

有关详细信息,请参阅UNIX上dd的手册页。

您可以使用RMAN。 从文件系统到裸设备:

1
2
3
4
5
RMAN> run {
2> allocate channel c1 type disk;
3> copy datafile '/u01/oradata/test_ts.dbf' to '/dev/raw/raw1';
4> }

从裸设备到文件系统:

1
2
3
4
5
RMAN> run {
2> allocate channel c1 type disk;
3> copy datafile '/dev/raw/raw1' to '/u01/oradata/test_ts.dbf';
4> }

如果不使用并行服务器或实时应用集群,我可以混合使用裸设备吗?

是的。缺点是这会使您的备份策略变得更加复杂。

我应该将重做日志文件存储在裸分区上吗?

重做日志特别适合位于裸分区上,因为它们是写密集型的,而且还会顺序写入。

我可以使用裸分区来存储归档日志吗?

不可以。归档日志必须存储在带有UNIX文件系统的分区上。

一个裸分区上可以有多个数据文件吗?

不可以。这意味着在设置裸分区时应该小心。如果分区太小,当空间用尽时将需要重新组织,而如果分区太大,则会浪费文件未使用的空间。

我的裸分区应该位于同一个磁盘设备上吗?

这是不推荐的,因为可能会出现争用。您应该将裸设备放置在不同的磁盘上,这些磁盘还应该连接到不同的控制器。

我需要将我的裸分区都设置成相同的大小吗?

这不是必须的,但这样做可以在需要更改数据库配置时提供灵活性。

如果决定使用裸设备,我需要更改任何UNIX内核参数吗?

不需要。

还有哪些UNIX级别的更改可能有助于提高I/O性能?

根据应用程序特性,尤其是它是读密集型、写密集型还是混合型,RAID和磁盘镜像可能会有所帮助。

在考虑了上述所有因素后,我还能获得哪些性能提升?

您需要为您的系统购买更多的磁盘驱动器和控制器,以在设备之间分散I/O负载。

裸存储支持Oracle database clusterware 12c吗?

不支持。从Oracle数据库12c开始,Oracle数据库及相关技术(如Oracle Clusterware)不再支持直接使用裸(块)存储设备。这意味着在升级到Oracle Clusterware 12c之前,文件必须移动到Oracle ASM或支持的共享文件系统(集群文件系统或网络文件系统(NFS))。