在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
二、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*显示正确的属主和权限即可。