在Oracle RAC环境中,ASM磁盘设备的命名和权限管理是一个关键问题。Linux系统重启后,SCSI设备名(如/dev/sdb、/dev/sdc)可能会发生变化,导致ASM无法正确识别磁盘。本文详细介绍如何使用UDEV机制实现ASM存储设备的持久化绑定,覆盖RHEL/OEL 6、7、8及更高版本。

一、为什么选择UDEV而非ASMLIB?

1.1 ASMLIB的局限性

Oracle ASMLIB曾是Linux平台上管理ASM磁盘的官方工具,但存在以下问题:

  • 版本依赖严重:需要与内核版本精确匹配的驱动模块
  • 维护成本高:内核升级后需要重新编译或更新ASMLIB
  • RHEL 6+不再提供:Red Hat从RHEL 6开始不再提供ASMLIB内核模块
  • 故障排查困难:ASMLIB问题往往难以诊断

1.2 UDEV的优势

  • 系统原生支持:无需额外安装任何软件包
  • 稳定可靠:基于设备唯一标识符(WWID/UUID),不受设备枚举顺序影响
  • 维护简单:内核升级不影响UDEV规则
  • 业界最佳实践:Oracle官方和Red Hat均推荐使用UDEV

相关阅读Why ASMLIB and why not?

二、UDEV工作原理

UDEV是Linux内核的设备管理器,负责在/dev目录下动态创建设备节点。其核心工作流程:

内核检测到设备 → 发送uevent事件 → UDEV守护进程接收 → 匹配规则文件 → 创建/修改设备节点

UDEV规则文件位于:

  • /etc/udev/rules.d/ - 自定义规则(优先级最高)
  • /usr/lib/udev/rules.d/ - 系统默认规则

规则文件按文件名排序执行,数字越大优先级越高。我们使用99-oracle-asmdevices.rules确保ASM规则最后执行。

三、不同Linux版本的配置差异

Linux版本 scsi_id命令语法 UDEV关键字 重载命令
RHEL/OEL 5 scsi_id -g -u -s /block/sdX BUS /sbin/start_udev
RHEL/OEL 6 scsi_id --whitelisted --replace-whitespace --device=/dev/sdX BUS 或 SUBSYSTEM /sbin/start_udev
RHEL/OEL 7 /usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/sdX SUBSYSTEM udevadm trigger
RHEL/OEL 8/9 /usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/sdX SUBSYSTEM udevadm trigger

四、RHEL/OEL 6 配置步骤

4.1 确认系统版本

[root@rac1 ~]# cat /etc/oracle-release
Oracle Linux Server release 6.10

# 或者
[root@rac1 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.10 (Santiago)

4.2 配置scsi_id白名单

RHEL 6默认不输出本地SCSI设备的ID,需要添加配置:

# 创建或追加配置
echo "options=--whitelisted --replace-whitespace" >> /etc/scsi_id.config

4.3 识别需要绑定的磁盘

# 查看所有块设备
[root@rac1 ~]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0   50G  0 disk 
├─sda1   8:1    0  500M  0 part /boot
└─sda2   8:2    0 49.5G  0 part 
sdb      8:16   0   10G  0 disk    # ← ASM磁盘
sdc      8:32   0   10G  0 disk    # ← ASM磁盘
sdd      8:48   0   10G  0 disk    # ← ASM磁盘
sde      8:64   0    5G  0 disk    # ← ASM磁盘
sdf      8:80   0    5G  0 disk    # ← ASM磁盘

# 获取磁盘的SCSI ID
[root@rac1 ~]# /sbin/scsi_id --whitelisted --replace-whitespace --device=/dev/sdb
1ATA_VBOX_HARDDISK_VB09cadb31-cfbea255

[root@rac1 ~]# /sbin/scsi_id --whitelisted --replace-whitespace --device=/dev/sdc
1ATA_VBOX_HARDDISK_VB5f097069-59efb82f

4.4 生成UDEV规则文件

方法一:使用自动化脚本(推荐)

#!/bin/bash
#====================================================================
# Oracle ASM UDEV规则自动生成脚本
# 适用于:RHEL/OEL 6.x
# 作者:Maclean Liu
#====================================================================

# 定义需要绑定的磁盘(根据实际情况修改)
DISKS="b c d e f"

# 规则文件路径
RULES_FILE="/etc/udev/rules.d/99-oracle-asmdevices.rules"

# 清空或创建规则文件
> ${RULES_FILE}

# 生成规则
for i in ${DISKS}; do
    SCSI_ID=$(/sbin/scsi_id --whitelisted --replace-whitespace --device=/dev/sd${i})
    if [ -n "${SCSI_ID}" ]; then
        echo "KERNEL==\"sd*\", BUS==\"scsi\", PROGRAM==\"/sbin/scsi_id --whitelisted --replace-whitespace --device=/dev/\$name\", RESULT==\"${SCSI_ID}\", NAME=\"asm-disk${i}\", OWNER=\"grid\", GROUP=\"asmadmin\", MODE=\"0660\"" >> ${RULES_FILE}
        echo "已添加: /dev/sd${i} -> /dev/asm-disk${i} (${SCSI_ID})"
    else
        echo "警告: /dev/sd${i} 无法获取SCSI ID,跳过"
    fi
done

echo ""
echo "规则文件已生成: ${RULES_FILE}"
cat ${RULES_FILE}

方法二:手动创建规则文件

# 创建规则文件
cat > /etc/udev/rules.d/99-oracle-asmdevices.rules << 'EOF'
# Oracle ASM Device Rules - RHEL/OEL 6
# Created: 2025-01-18

KERNEL=="sd*", BUS=="scsi", PROGRAM=="/sbin/scsi_id --whitelisted --replace-whitespace --device=/dev/$name", RESULT=="1ATA_VBOX_HARDDISK_VB09cadb31-cfbea255", NAME="asm-diskb", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="sd*", BUS=="scsi", PROGRAM=="/sbin/scsi_id --whitelisted --replace-whitespace --device=/dev/$name", RESULT=="1ATA_VBOX_HARDDISK_VB5f097069-59efb82f", NAME="asm-diskc", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="sd*", BUS=="scsi", PROGRAM=="/sbin/scsi_id --whitelisted --replace-whitespace --device=/dev/$name", RESULT=="1ATA_VBOX_HARDDISK_VB4e1a81c0-20478bc4", NAME="asm-diskd", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="sd*", BUS=="scsi", PROGRAM=="/sbin/scsi_id --whitelisted --replace-whitespace --device=/dev/$name", RESULT=="1ATA_VBOX_HARDDISK_VBdcce9285-b13c5a27", NAME="asm-diske", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="sd*", BUS=="scsi", PROGRAM=="/sbin/scsi_id --whitelisted --replace-whitespace --device=/dev/$name", RESULT=="1ATA_VBOX_HARDDISK_VB82effe1a-dbca7dff", NAME="asm-diskf", OWNER="grid", GROUP="asmadmin", MODE="0660"
EOF

4.5 加载UDEV规则

# RHEL/OEL 6
/sbin/start_udev

# 验证设备创建
[root@rac1 ~]# ls -l /dev/asm*
brw-rw----. 1 grid asmadmin 8, 16 Jan 18 10:30 /dev/asm-diskb
brw-rw----. 1 grid asmadmin 8, 32 Jan 18 10:30 /dev/asm-diskc
brw-rw----. 1 grid asmadmin 8, 48 Jan 18 10:30 /dev/asm-diskd
brw-rw----. 1 grid asmadmin 8, 64 Jan 18 10:30 /dev/asm-diske
brw-rw----. 1 grid asmadmin 8, 80 Jan 18 10:30 /dev/asm-diskf

五、RHEL/OEL 7/8/9 配置步骤

5.1 主要变化

  • scsi_id路径变更为/usr/lib/udev/scsi_id
  • UDEV规则中BUS关键字改为SUBSYSTEM
  • 使用udevadm命令管理UDEV

5.2 获取磁盘SCSI ID

# RHEL/OEL 7/8/9
[root@rac1 ~]# /usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/sdb
360000000000000000e00000000010001

# 批量获取
for disk in sdb sdc sdd sde sdf; do
    echo "/dev/${disk}: $(/usr/lib/udev/scsi_id -g -u -d /dev/${disk})"
done

5.3 生成UDEV规则文件

#!/bin/bash
#====================================================================
# Oracle ASM UDEV规则自动生成脚本
# 适用于:RHEL/OEL 7.x / 8.x / 9.x
#====================================================================

DISKS="b c d e f"
RULES_FILE="/etc/udev/rules.d/99-oracle-asmdevices.rules"

> ${RULES_FILE}

for i in ${DISKS}; do
    SCSI_ID=$(/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/sd${i})
    if [ -n "${SCSI_ID}" ]; then
        echo "KERNEL==\"sd*\", SUBSYSTEM==\"block\", PROGRAM==\"/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/\$name\", RESULT==\"${SCSI_ID}\", SYMLINK+=\"asm-disk${i}\", OWNER=\"grid\", GROUP=\"asmadmin\", MODE=\"0660\"" >> ${RULES_FILE}
        echo "已添加: /dev/sd${i} -> /dev/asm-disk${i}"
    fi
done

echo "规则文件内容:"
cat ${RULES_FILE}

注意:RHEL 7+推荐使用SYMLINK+=创建符号链接,而非NAME=重命名设备。这样原始设备名(/dev/sdX)仍然可用。

5.4 加载并验证规则

# 重新加载UDEV规则
udevadm control --reload-rules

# 触发设备重新识别
udevadm trigger --type=devices --action=change

# 验证设备
ls -l /dev/asm*

# 查看详细设备信息
udevadm info --query=all --name=/dev/asm-diskb

六、多路径环境配置

在使用多路径(Multipath)的生产环境中,应对多路径设备(如/dev/mapper/mpathX)进行UDEV绑定,而非底层的/dev/sdX设备。

6.1 查看多路径设备

[root@rac1 ~]# multipath -ll
mpatha (360000000000000000e00000000010001) dm-2 NETAPP,LUN
size=100G features='3 queue_if_no_path pg_init_retries 50' hwhandler='1 alua' wp=rw
|-+- policy='service-time 0' prio=50 status=active
| |- 1:0:0:1 sdb 8:16  active ready running
| `- 2:0:0:1 sdd 8:48  active ready running
`-+- policy='service-time 0' prio=10 status=enabled
  |- 1:0:1:1 sdc 8:32  active ready running
  `- 2:0:1:1 sde 8:64  active ready running

6.2 多路径设备的UDEV规则

# 获取多路径设备的WWID
[root@rac1 ~]# /usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/dm-2
360000000000000000e00000000010001

# 或从multipath输出中获取WWID(括号内的值)

# 创建规则文件
cat > /etc/udev/rules.d/99-oracle-asmdevices.rules << 'EOF'
# Oracle ASM Device Rules - Multipath Environment
# 注意:针对dm-*设备或mpath设备配置

KERNEL=="dm-*", ENV{DM_UUID}=="mpath-360000000000000000e00000000010001", SYMLINK+="asm-disk1", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="dm-*", ENV{DM_UUID}=="mpath-360000000000000000e00000000010002", SYMLINK+="asm-disk2", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="dm-*", ENV{DM_UUID}=="mpath-360000000000000000e00000000010003", SYMLINK+="asm-disk3", OWNER="grid", GROUP="asmadmin", MODE="0660"
EOF

6.3 使用/dev/disk/by-id路径

另一种方式是直接使用系统生成的by-id路径:

# 查看by-id链接
ls -l /dev/disk/by-id/ | grep -v part

# ASM可以直接使用这些路径
/dev/disk/by-id/scsi-360000000000000000e00000000010001

七、VMware/VirtualBox环境注意事项

7.1 VMware配置

VMware默认不暴露磁盘UUID,需要在虚拟机配置文件中添加:

# 编辑.vmx文件,添加以下行
disk.EnableUUID = "TRUE"

7.2 VirtualBox配置

VirtualBox默认支持SCSI ID,但建议使用SATA或SCSI控制器而非IDE:

# 使用VBoxManage设置磁盘UUID
VBoxManage internalcommands sethduuid /path/to/disk.vdi

八、故障排除

8.1 scsi_id返回空值

# 问题:scsi_id命令无输出
/sbin/scsi_id --whitelisted --replace-whitespace --device=/dev/sdb
# (无输出)

# 解决方案1:确认scsi_id.config配置
cat /etc/scsi_id.config
# 应包含: options=--whitelisted --replace-whitespace

# 解决方案2:检查磁盘是否为本地SCSI设备
lsscsi
# [0:0:0:0]    disk    ATA      VBOX HARDDISK    1.0   /dev/sdb

# 解决方案3:VMware环境确认disk.EnableUUID
grep -i uuid /path/to/vm.vmx

8.2 UDEV规则不生效

# 检查规则语法
udevadm test /sys/block/sdb 2>&1 | grep -E "(OWNER|GROUP|MODE|NAME|SYMLINK)"

# 查看UDEV日志
journalctl -u systemd-udevd -f

# 手动触发规则
udevadm trigger --verbose --type=devices --action=change --subsystem-match=block

8.3 OUI/ASMCA报设备不共享

这是一个已知Bug,安装时可以忽略此警告,ASM磁盘实际上是可以正常使用的。

# 错误信息示例
"/dev/asm-disk1" is not shared
Unable to determine the sharedness of /dev/asm-disk1

# 解决方案:忽略该警告继续安装
# 或手动在ASMCA中指定磁盘发现路径: /dev/asm*

8.4 添加新磁盘后CRS资源异常

# 正确的添加新磁盘流程:

# 1. 添加新磁盘的UDEV规则到规则文件
vi /etc/udev/rules.d/99-oracle-asmdevices.rules

# 2. 仅触发新设备,不重启整个UDEV
udevadm trigger --type=devices --action=add --subsystem-match=block

# 3. 验证新设备
ls -l /dev/asm*

# 注意:不要在生产环境运行 start_udev 或 udevadm trigger --action=change
# 这可能导致CRS资源短暂中断

九、UDEV规则语法参考

9.1 常用匹配键

匹配键 说明 示例
KERNEL 内核设备名 KERNEL=="sd*"
SUBSYSTEM 子系统类型 SUBSYSTEM=="block"
PROGRAM 执行外部程序获取值 PROGRAM=="/sbin/scsi_id ..."
RESULT 匹配PROGRAM的输出 RESULT=="360000..."
ENV{key} 匹配环境变量 ENV{DM_UUID}=="mpath-..."
ATTR{file} 匹配sysfs属性 ATTR{size}=="20971520"

9.2 常用赋值键

赋值键 说明 示例
NAME 设备节点名称(重命名) NAME="asm-disk1"
SYMLINK 创建符号链接 SYMLINK+="asm-disk1"
OWNER 设备属主 OWNER="grid"
GROUP 设备属组 GROUP="asmadmin"
MODE 设备权限 MODE="0660"

十、完整配置示例

10.1 单路径环境(RHEL 7+)

#!/bin/bash
#====================================================================
# Oracle RAC ASM UDEV配置完整脚本
# 适用于:RHEL/OEL 7.x / 8.x / 9.x 单路径环境
# 用法:以root用户执行,根据提示修改DISKS变量
#====================================================================

set -e

# ============ 配置区域 ============
# 修改为实际需要绑定的磁盘字母
DISKS="b c d e f"
ASM_OWNER="grid"
ASM_GROUP="asmadmin"
RULES_FILE="/etc/udev/rules.d/99-oracle-asmdevices.rules"

# ============ 检查环境 ============
echo "=========================================="
echo "Oracle ASM UDEV配置脚本"
echo "=========================================="

if [ "$(id -u)" != "0" ]; then
    echo "错误:请以root用户执行此脚本"
    exit 1
fi

# 确认用户和组存在
if ! id "${ASM_OWNER}" &>/dev/null; then
    echo "错误:用户 ${ASM_OWNER} 不存在"
    exit 1
fi

if ! getent group "${ASM_GROUP}" &>/dev/null; then
    echo "错误:组 ${ASM_GROUP} 不存在"
    exit 1
fi

# ============ 生成规则 ============
echo ""
echo "正在生成UDEV规则..."
> ${RULES_FILE}

echo "# Oracle ASM Device Rules" >> ${RULES_FILE}
echo "# Generated: $(date)" >> ${RULES_FILE}
echo "" >> ${RULES_FILE}

for i in ${DISKS}; do
    DEVICE="/dev/sd${i}"
    if [ -b "${DEVICE}" ]; then
        SCSI_ID=$(/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=${DEVICE} 2>/dev/null)
        if [ -n "${SCSI_ID}" ]; then
            echo "KERNEL==\"sd*\", SUBSYSTEM==\"block\", PROGRAM==\"/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/\$name\", RESULT==\"${SCSI_ID}\", SYMLINK+=\"asm-disk${i}\", OWNER=\"${ASM_OWNER}\", GROUP=\"${ASM_GROUP}\", MODE=\"0660\"" >> ${RULES_FILE}
            echo "  ✓ ${DEVICE} -> /dev/asm-disk${i} (${SCSI_ID:0:20}...)"
        else
            echo "  ✗ ${DEVICE} - 无法获取SCSI ID"
        fi
    else
        echo "  ✗ ${DEVICE} - 设备不存在"
    fi
done

# ============ 加载规则 ============
echo ""
echo "正在加载UDEV规则..."
udevadm control --reload-rules
udevadm trigger --type=devices --action=change --subsystem-match=block

# ============ 验证结果 ============
echo ""
echo "=========================================="
echo "配置完成!当前ASM设备:"
echo "=========================================="
ls -l /dev/asm* 2>/dev/null || echo "未发现ASM设备"

echo ""
echo "规则文件位置: ${RULES_FILE}"

10.2 RAC双节点验证

# 在所有RAC节点上执行相同配置后,验证SCSI ID一致性:

# 节点1
[root@rac1 ~]# /usr/lib/udev/scsi_id -g -u -d /dev/asm-diskb
360000000000000000e00000000010001

# 节点2
[root@rac2 ~]# /usr/lib/udev/scsi_id -g -u -d /dev/asm-diskb
360000000000000000e00000000010001

# 两个节点的SCSI ID必须完全相同!

常见问题FAQ

Q1: 使用UDEV后,还需要安装ASMLIB吗?

不需要。UDEV完全可以替代ASMLIB的功能,且更加稳定可靠。

Q2: 添加新磁盘时需要停止数据库吗?

不需要。只需添加新规则并执行udevadm trigger即可,不会影响现有ASM磁盘组。

Q3: 多路径环境是否可以使用UDEV?

可以。但应该对多路径设备(dm-*)进行绑定,而非底层物理设备。

Q4: ASM磁盘需要分区吗?

不需要。ASM可以直接使用整个磁盘设备,无需分区。

Q5: 为什么OUI检查报设备权限错误?

这是一个已知Bug,可以忽略。只要ls -l /dev/asm*显示正确的属主和权限即可。