Aekor

Aekor
专注于用户阅读体验的响应式博客主题
  1. 首页
  2. Oracle 数据库
  3. 正文

Oracle ASM 磁盘组扩容:asmlib 与 udev 两种方式

2026-02-28 28750点热度 0人点赞 0条评论

数据文件所在的 ASM 磁盘组快满时,扩容本身不复杂,容易出问题的是前置判断:新盘在两个节点上是否都能看到、应该用 asmlib 还是 udev 绑定、分区后要不要在节点二刷新、加盘后 rebalance 要跑多久。本文把两种方式放在一起讲,先给选择依据,再分别给出可复制执行的流程,最后用同一组视图验证结果。

示例环境是两节点 RAC,新增一块 200G 裸盘,未做多路径。asmlib 流程中的新盘为 /dev/sdk,udev 流程中的新盘为 /dev/sdi。盘符、大小和磁盘组名都要按实际环境替换,不要照抄。

先判断用哪种方式

两种方式最终都是把一个块设备交给 ASM,区别在于“谁负责把设备名固定下来”。

维度asmlibudev
依赖oracleasm 服务及内核模块系统自带 udev、scsi_id
磁盘名createdisk 时指定,路径为 /dev/oracleasm/disks/ 下规则里用 SYMLINK 指定,如 /dev/asm-diskd
节点一致性每个节点执行 scandisks每个节点放置相同的规则文件
适合场景存量库已经在用 asmlib新环境、希望少一层内核模块依赖

判断原则很简单:现有磁盘组用哪种,就延续哪种,不要在一个磁盘组里混用两套命名体系。新环境如果没有历史包袱,udev 用 WWID 绑定,重启后盘符变化也不会影响 ASM;asmlib 的名字更直观,但依赖 oracleasm 服务,节点上少装一个包就跑不起来。

无论选哪种,动手前先确认这几件事:

  • 两个节点都能看到同一块新盘,且盘的 WWID/序列号一致。
  • 新盘没有被文件系统、LVM 或其他磁盘组占用。
  • 已有数据库备份,扩容安排在业务低峰;rebalance 会持续占用 I/O。
  • 磁盘组名、冗余级别、剩余空间已确认,新增容量要按冗余级别折算。

扩容前的容量测算

加盘之前先把“还差多少”算清楚,避免加完发现仍然不够。查磁盘组整体水位:

set linesize 200
col name for a20
select name,state,total_mb,free_mb,
       round((total_mb-free_mb)/total_mb*100,2) used_pct
from v$asm_diskgroup
order by name;

再看每个磁盘的使用是否均衡。某个盘明显比其他盘满,说明之前的 rebalance 没有跑完,或者磁盘大小不一致:

select group_number,disk_number,name,total_mb,free_mb,
       round((total_mb-free_mb)/total_mb*100,2) used_pct
from v$asm_disk
order by group_number,disk_number;

需要的容量按“业务增长量 ÷ 冗余折算系数”估算。external 冗余可用容量约等于裸容量,normal 约一半,high 约三分之一;再预留 15%–20% 给 rebalance 和突发增长,不要按 100% 用满。磁盘组长期高于 85% 时,除了加盘,还要检查是否有归档、临时文件或审计表在异常增长。

方式一:asmlib 扩容

1. 确认新盘和添加时间

[root@if-db01 ~]# ls -lrth /dev/sdk
brw-rw---- 1 root disk 8, 160 Jul 31 10:16 /dev/sdk
[root@if-db02 ~]# ls -lrth /dev/sdk
brw-rw---- 1 root disk 8, 160 Jul 31 10:19 /dev/sdk

两个节点看到的时间可能差几分钟,这是正常的。重点确认设备号、大小和权限一致;如果节点二根本没有这个设备,先解决存储映射,不要继续分区。

原文记录该盘的序列号为:

Serial number:        6000c29f225306dbce07eed464682681

2. 分区

[root@if-db01 ~]# fdisk /dev/sdk
欢迎使用 fdisk (util-linux 2.23.2)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。
Device does not contain a recognized partition table
使用磁盘标识符 0x5554dbd5 创建新的 DOS 磁盘标签。
命令(输入 m 获取帮助):n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p):
Using default response p
分区号 (1-4,默认 1):
起始 扇区 (2048-83886079,默认为 2048):
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-83886079,默认为 83886079):
将使用默认值 83886079
分区 1 已设置为 Linux 类型,大小设为 200 GiB
命令(输入 m 获取帮助):
命令(输入 m 获取帮助):w
The partition table has been altered!
Calling ioctl() to re-read partition table.
正在同步磁盘。

分区完成后,节点一的内核已经识别到 /dev/sdk1,节点二还没有。必须在节点二刷新分区表:

[root@if-db02 ~]# partprobe /dev/sdk

这一步漏掉的典型现象是:节点一 createdisk 成功,节点二 scandisks 之后仍然看不到新盘。

3. 确认现有 ASM 磁盘

[root@if-db01 ~]# /etc/init.d/oracleasm listdisks
OCRDG01
ARCHDG01
DATADG01

先确认 DATADG02 这个名称没有被占用。ASM 磁盘名在集群内必须唯一,重复创建会报错,也不会覆盖已有磁盘。

4. 创建 ASM 磁盘

[root@if-db01 ~]# /etc/init.d/oracleasm createdisk DATADG02 /dev/sdk1

createdisk 只需要在节点一执行。它会把分区标记为 ASM 磁盘,并在 /dev/oracleasm/disks/ 下生成对应设备。

5. 节点二扫描并确认

[root@if-db02 ~]# /etc/init.d/oracleasm listdisk
OCRDG01
ARCHDG01
DATADG01

[root@if-db02 ~]# /etc/init.d/oracleasm scandisks

[root@if-db02 ~]# /etc/init.d/oracleasm listdisk
OCRDG01
ARCHDG01
DATADG01
DATADG02

原文节点二使用的是 listdisk,实际命令是 listdisks;如果执行时报“命令不存在”,换成复数形式即可。判断标准不是命令有没有输出,而是第二次列表里是否出现了 DATADG02。

6. 以 sysasm 身份查看磁盘组

[root@if-db01 ~]# su - grid
-- 进入sysam用户
[grid@if-db01 ~]# sqlplus / as sysasm
-- 查看数据库盘符组
set linesize 600
select name,STATE,TOTAL_MB,FREE_MB,VOTING_FILES from v$asm_diskgroup;

-- 查看数据盘符组状态
set pagesize 900
set linesize 900
col MOUNT_STATUS for a30
col HEADER_STATUS for a10
col STATE for a6
col path for a40
select DISK_NUMBER,GROUP_NUMBER,MOUNT_STATUS,HEADER_STATUS,STATE,TOTAL_MB,FREE_MB,NAME,PATH,CREATE_DATE,MOUNT_DATE from v$asm_disk;

这里要确认两件事:DATADG 处于 MOUNTED 状态;v$asm_disk 里没有同名或同路径的旧记录。

7. 加入磁盘组并监控 rebalance

-- 添加磁盘到数据盘符组
alter diskgroup DATADG add disk '/dev/oracleasm/disks/DATADG02' rebalance power 6;

-- 查看自动平衡的工作进度
select * from v$asm_operation;

power 6 是 rebalance 的并行度,取值范围通常是 1 到 11。值越大,平衡越快,但对存储和业务的 I/O 冲击也越大。生产库在业务时段建议用较低的 power,或者等维护窗口再提高;不要在业务高峰直接照抄 6。

方式二:udev 扩容

udev 的核心是用磁盘的 WWID 生成一个固定符号链接。盘符 /dev/sdi 可能变化,WWID 不会。

1. 获取 WWID

/usr/lib/udev/scsi_id -g -u -d /dev/sdi
36000c29c93dea3b8028e2c0d21dd7000

两个节点都要执行,确认输出完全一致。若不一致,说明看到的不是同一块盘,后续规则一定不能继续写。

2. 备份并修改 udev 规则

RAC 环境双节点都需要添加。添加前先备份原文件:

cp /usr/lib/udev/rules.d/99-oracle-asmdevices.rules /usr/lib/udev/rules.d/99-oracle-asmdevices.rules.$(date +%F)

然后追加规则:

cat /usr/lib/udev/rules.d/99-oracle-asmdevices.rules
......
KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM=="/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/$name", RESULT=="36000c29c93dea3b8028e2c0d21dd7000", SYMLINK+="asm-diskd", OWNER="grid", GROUP="asmadmin", MODE="0660"

几个参数不要改错:

  • RESULT 必须和上一步的 WWID 完全一致。
  • SYMLINK 是本节点使用的固定路径,示例为 /dev/asm-diskd。
  • OWNER/GROUP 要能让 grid 用户读写,通常是 grid:asmadmin,权限 0660。
  • 规则文件在两个节点上保持一致,但每块盘只能有一条对应 WWID 的规则。

3. 重新加载规则

RAC 环境双节点都需要执行:

/sbin/udevadm trigger --type=devices --action=change

执行后建议确认符号链接已经生成、属主正确:

ls -l /dev/asm-diskd

原文没有记录这条检查命令,但它能提前发现“规则写了但没生效”的问题,避免到 alter diskgroup 才报路径不存在。

4. 查看磁盘组并加入新盘

su - grid
sqlplus / as sysasm
set linesize 600
select name,STATE,TOTAL_MB,FREE_MB,VOTING_FILES from v$asm_diskgroup;

-- 查看数据盘符组状态
set pagesize 900
set linesize 900
col MOUNT_STATUS for a30
col HEADER_STATUS for a10
col STATE for a6
col path for a40
select DISK_NUMBER,GROUP_NUMBER,MOUNT_STATUS,HEADER_STATUS,STATE,TOTAL_MB,FREE_MB,NAME,PATH,CREATE_DATE,MOUNT_DATE from v$asm_disk;

确认新设备可见后加盘:

-- 添加磁盘到数据盘符组
alter diskgroup DATADG add disk '/dev/asm-diskd' rebalance power 6;;

原文这条语句末尾是两个分号(;;),代码块按原文保留。SQL*Plus 会把多余的分号当成空语句,通常不报错;实际执行时写一个即可。

5. 查看挂载和平衡情况

set lines 200 pages 50000
col name for a25
col path for a55
select group_number,disk_number,name,path,total_mb/1024 total_G,path,mode_status,repair_timer from v$asm_disk order by group_number,disk_number;

-- 查看自动平衡的工作进度
select * from v$asm_operation;

多路径环境的差异

原文这次是裸盘直通,没有做多路径,所以 udev 规则直接绑定 /dev/sdi 的 WWID,asmlib 直接对 /dev/sdk1 执行 createdisk。如果存储侧做了 multipath,做法要改两处。

第一,绑定对象换成 multipath 设备,而不是物理盘。先确认 multipath -ll 输出里的 WWID 和 /dev/mapper/ 下的设备名,再对 /dev/mapper/xxx 取 scsi_id,或者在规则里直接用 ENV{DM_UUID} 匹配。对物理盘 /dev/sdX 绑定,多路径切换后符号链接会指向一条已经失效的链路。

第二,asmlib 的 createdisk 也要传 multipath 设备名(/dev/mapper/xxx),不要传 /dev/sdk1。否则 ASM 只认其中一条路径,另一条路径的故障切换对它没有意义。

判断是否已经正确接管,可以看 v$asm_disk 的 PATH 列:多路径环境下应该是 /dev/mapper/ 开头的路径,而不是 /dev/sd 开头。这一列在加盘后要专门确认一次。

另外,多路径环境下新加 LUN 后需要先 multipath -r 重新加载配置,再执行 partprobe。顺序反了,udev 规则可能匹配不到设备。原文环境没有这一层,照抄流程时容易漏掉。

两个节点的检查顺序

扩容时最容易漏的是“只在节点一验证”。正确的检查顺序是:

  1. 两个节点分别 ls -lrth /dev/sdk(或对应的 udev 符号链接),确认设备存在、权限一致。
  2. 两个节点分别 scsi_id 取 WWID,确认一致(udev 方式)。
  3. 节点一 createdisk,节点二 scandisks 后 listdisks 确认能看到。
  4. 任意一个节点的 ASM 实例执行 alter diskgroup ... add disk,ASM 会自动同步到另一个节点。
  5. 两个节点分别查 v$asm_disk,确认 PATH 和 MOUNT_STATUS 一致。

第 4 步不需要在两个节点各执行一次。add disk 是集群级操作,重复执行会报磁盘已在组内。如果节点二的视图里暂时看不到新盘,先等几秒再查,不要立刻重复加盘。

lsdsk 的输出也可以在两个节点分别执行一次做对比,正常情况下两个节点看到的成员列表应该完全相同。节点二缺少新盘,通常是 udev 规则没生效或 oracleasm scandisks 没跑,回到对应步骤排查。

统一验证

两种方式加盘完成后,验证动作是一样的。

先看磁盘组容量。TOTAL_MB 应该增加,FREE_MB 也会随之增加;如果是 normal/high redundancy,可用容量不等于裸盘容量,要按故障组折算。

set linesize 600
select name,STATE,TOTAL_MB,FREE_MB,VOTING_FILES from v$asm_diskgroup;

再看新盘是否真正属于目标磁盘组,状态是否为 NORMAL:

set pagesize 900
set linesize 900
col MOUNT_STATUS for a30
col HEADER_STATUS for a10
col STATE for a6
col path for a40
select DISK_NUMBER,GROUP_NUMBER,MOUNT_STATUS,HEADER_STATUS,STATE,TOTAL_MB,FREE_MB,NAME,PATH,CREATE_DATE,MOUNT_DATE from v$asm_disk;

最后看 rebalance 是否结束:

select * from v$asm_operation;

v$asm_operation 有记录,说明平衡还在进行;查询返回空行,才表示本次操作完成。重点看 OPERATION(应为 REBALANCE)、STATE、POWER/ACTUAL_POWER、SOFAR、EST_WORK、EST_RATE 和 EST_MINUTES。EST_MINUTES 只是估算,会随着 I/O 情况变化,不要用它判断是否卡死;判断依据是 SOFAR 是否持续增长。

在 rebalance 期间不要重启集群、不要下线磁盘,也不要执行其他会改变磁盘组结构的操作。需要确认进度时,反复查 v$asm_operation 即可,不要重复执行 add disk。

用 asmcmd 交叉确认

视图之外,再用 asmcmd 看一眼磁盘组的成员,能快速确认新盘的路径和状态:

asmcmd lsdsk -G DATADG

输出里 asmlib 方式的路径是 /dev/oracleasm/disks/DATADG02,udev 方式是 /dev/asm-diskd。如果新盘出现在 lsdsk 里但不在 v$asm_disk 中,说明磁盘头还没被 ASM 识别,先查 ASM 告警日志里有没有 ORA-15000 系列的报错,不要急着重复执行 add disk。

扩容期间也建议盯一下 ASM 告警日志($ORACLE_BASE/diag/asm/+asm/+ASM1/trace/alert_+ASM1.log,实例名按实际替换),重点看有没有磁盘离线、读错误或 rebalance 失败的记录。存储侧的链路抖动在视图里未必立刻体现,但告警日志通常会先报出来。

加错盘怎么退

如果新盘加进了错误的磁盘组,或者加完发现盘本身有问题,可以在 ASM 实例里把磁盘摘掉:

alter diskgroup DATADG drop disk DATADG02 rebalance power 4;

这条命令会触发一次反向 rebalance,把该盘上的数据迁走,不是立即生效。执行后必须用 v$asm_operation 确认迁移完成,再检查 v$asm_disk 中该盘是否已消失。迁移期间同样有 I/O 压力,且磁盘组剩余空间必须够承接这部分数据,否则可能失败。drop 之前确认磁盘名没有写错——摘错盘会直接触发冗余降级。

风险与注意事项

盘符漂移。 原文明确这次是裸盘、没有做多路径。asmlib 方式在 createdisk 之后由 ASM 管理,重启影响较小;udev 方式靠 WWID 绑定,也不依赖 /dev/sdX 不变。真正危险的是在 udev 规则里写错 WWID,或者两个节点用了不同的规则,导致同一个 ASM 磁盘在不同节点映射到不同设备。

不要在 OS 层重新格式化。createdisk 或 udev 绑定完成后,这块盘就交给 ASM 了。再执行 mkfs、重新分区或加入 LVM,会破坏 ASM 头。

rebalance 的 I/O 成本。power 6 不是固定推荐值。数据量大、存储性能一般时,先低 power 跑,观察业务响应和存储延迟,再决定是否提高。扩容期间归档备份、大批量导入等重 I/O 任务应错开。

扩容不等于空间立刻可用。 新盘加入后要等 rebalance 完成,数据才真正重新分布;在完成前,FREE_MB 的读数可能波动。

操作前备份。 磁盘组扩容本身一般不动数据文件,但误加盘、加错磁盘组、规则写错都可能引发故障。至少确认数据库有可用备份,并记录当前 v$asm_diskgroup/v$asm_disk 的输出,便于回退比对。

排错清单

  • 节点二看不到新分区:先在节点二执行 partprobe /dev/sdk,再 scandisks。
  • createdisk 报磁盘已存在:用 listdisks 确认名称,换一个未占用的磁盘名,不要强行覆盖。
  • 节点二 listdisks 仍没有新盘:检查 /dev/oracleasm/disks/ 下是否有对应设备,确认 oracleasm 服务在两个节点都正常。
  • udev 规则写了但 /dev/asm-diskd 不存在:确认 RESULT 与 scsi_id 输出一致,确认规则文件路径正确,再执行 udevadm trigger。
  • alter diskgroup 报路径不存在:先确认 ASM 实例能看到该路径,再检查权限和属主。
  • v$asm_operation 长时间有记录:看 SOFAR 是否增长、存储是否有异常延迟;不要因为 EST_MINUTES 变大就重启。

待核对

  • 原文节点二使用 listdisk,Oracle 的标准命令是 listdisks;代码块按原文保留,实际执行建议用复数形式。
  • 原文 udev 流程中 sqlpuls 为拼写错误,文中改为 sqlplus;alter diskgroup 末尾的 ;; 按原文保留。
  • asmlib 示例盘为 /dev/sdk(200G),udev 示例盘为 /dev/sdi,两者不是同一块盘,盘符和容量需按实际替换。
  • 原文未记录 ls -l /dev/asm-diskd 的输出,该检查为补充。
  • 原文未说明磁盘组冗余级别,实际可用容量需按 normal/high redundancy 折算。
  • alter diskgroup ... drop disk 为补充的回退命令,原文未涉及;执行前务必确认磁盘名,并在维护窗口操作。

原文首发于微信公众号「止水研习社」。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: ASM Oracle 存储扩容
最后更新:2026-10-17

Aekor

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

使用AI教程

  • API报错解决方案
  • API 基础知识
  • API Key 获取
  • 最新接入教程

分类

  • Blog
  • Oracle 数据库
  • TradingAgents-CN
  • 使用教程
  • 数据库

COPYRIGHT © 2026 Aekor. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang