☰
Oracle ASM命令行添加聚合磁盘实战:从语法到重平衡验证
2026/10/20 7:56:33 网站建设 项目流程

干这行十来年,ASM磁盘组的管理几乎每周都会碰到。今天想聊聊“Oracle ASM 命令行方式添加聚合磁盘”这件事。很多人看到“聚合磁盘”会愣一下,因为Oracle官方文档里其实没有这个标准名词,它更多是实践里的说法:把多块物理裸盘交给ASM去统一管理,组成一个磁盘组,从数据库视角看就是一块能扩容、能均衡I/O的“聚合存储”。标题既然带了“添加”,核心动作通常是往一个现成的磁盘组里追加新盘;如果你是要新建磁盘组,跑不掉的是同一套命令行体系,本文会把两件事一起讲清楚。

适合谁看?刚接手Oracle库的运维新人、备库环境加过盘却不敢在生产动手的人,或者每次都是图形界面点两下、搞不清背后发生了什么的人,都可以认真读一遍。我会尽量把所有命令、查询、排查思路都按生产环境能直接执行的标准来写,不搞花活。

1. 先搞明白:标题里的“聚合磁盘”到底指什么

1.1 两种常见含义,别一开始就做错

在Oracle官方文档里,你翻半天也找不到“聚合磁盘”这个术语。这个词通常是从存储领域借来的,大家日常沟通中用“聚合”来指“把多块物理盘通过ASM聚合成一个磁盘组”的能力。更常见的说法是“添加磁盘到磁盘组”“扩展ASM磁盘组”“往DATA组里加盘”。所以接到这个标题的需求,第一步不是敲命令,而是跟需求方确认:你要的是把一组新盘塞进现有磁盘组,还是把一堆裸盘打包创建一个新磁盘组。这两个动作的语法有交集,但后续影响、失败组划分方式、重平衡策略完全不同,千万别会错意。

如果你要的是前者,核心命令是ALTER DISKGROUP ... ADD DISK;如果是后者,核心是CREATE DISKGROUP ... DISK。本文以“添加”为主线,因为和“聚合”放在一起时,大多数人实际是想给现有存储池扩容,让新盘和旧盘融成一个逻辑整体。但为了方便查资料,创建磁盘组的语法我也会单独写一节。实战里我对同事的要求向来是:先把需求翻译成标准Oracle术语,再谈操作,能避免一半以上的误操作。

1.2 加盘后,ASM 内部到底发生了什么变化

向一个非外部冗余(NORMAL或HIGH)的磁盘组添加新盘,ASM会立刻把新盘纳入该磁盘组,为它分配磁盘号、建立磁盘目录项,然后触发一次重平衡。重平衡的本质是数据重新洗牌:ASM会在整个磁盘组范围内把内部镜像的extent切分、搬运,让分布更均匀。对NORMAL冗余来说,每个extent有两份拷贝,分别放在不同的失败组里。新增盘后,一部分原本堆在旧盘上的副本会被搬到新盘,目标是把I/O负载摊开。

这也是为什么添加磁盘不是一个瞬时操作。盘少的时候几分钟完事,盘多、数据量大时可能跑几小时甚至跨天,期间I/O会有明显压力。生产环境对I/O敏感的话,最好把重平衡Power调低,或者直接安排在业务低峰。很多新手最容易忽略的就是这一点:盘加进去,SQL执行完并不等于安全落地,要等V$ASM_OPERATION里没有正在运行的rebalance记录才算数。我后面会专门演示怎么查这个视图。

2. 开工之前:OS层磁盘准备与现场核查清单

2.1 新盘在操作系统上必须满足的四个条件

加盘不顺,十有八九不是ASM命令写错了,而是操作系统这一层没准备好。我习惯动手前按四步检查。

第一,OS必须能看到这块盘。Linux下用lsblk,AIX下用lspv;如果走的是多路径映射,先确认多路径软件已经把盘生成出来。这里有个容易踩的坑:存储侧把LUN映射给节点后,机器未必自动识别,需要重新扫描SCSI总线,或者通过存储管理软件在存储侧额外操作。总之,操作系统层面看不见,ASM再厉害也没有用。

第二,盘的权限和属主必须和ASM实例的运行用户一致。Linux UDEV方式常用grid:asmadmin,也有的环境是oracle:dba,取决于你安装时怎么定义。文件权限一般是0660。如果盘的权限不对,添加后ASM实例会报权限错误;尤其在RAC里,两台机器的盘权限不一致,会出现一个节点正常、另一个节点报错,排查起来非常痛苦。

第三,盘路径必须落在ASM_DISKSTRING的匹配范围内。例如参数值是/dev/oracleasm/disks/*,你把一块盘配成了/dev/sdm,ASM根本不会去扫描它。这个在runbook里要特别标注:先show parameter asm_diskstring,再用ls -l核对路径,别一上来就敲ALTER。

第四,磁盘头不能被旧数据污染。ASM要求新盘是“候选盘”状态,如果盘头有残留信息,ASM会拒绝使用。验证方式是用Kfed读盘头:

$ kfed read /dev/oracleasm/disks/ASMDATA09 | head -20

如果输出异常,说明盘头不干净。确认这块盘确实可以废弃后,清掉前端数据再使用:

dd if=/dev/zero of=/dev/oracleasm/disks/ASMDATA09 bs=1M count=128

注意:dd清盘前必须百分百确认设备名没有写错,一旦清错盘,后果不用我多说。这步做完,盘的状态才能重新被标记为CANDIDATE。

2.2 磁盘组现状摸查:往哪个失败组放新盘

在ASM实例执行下面两条SQL,先把家底盘清楚:

SELECT GROUP_NUMBER, NAME, TYPE, STATE, TOTAL_MB, FREE_MB, USABLE_FILE_MB FROM V$ASM_DISKGROUP; SELECT GROUP_NUMBER, DISK_NUMBER, NAME, PATH, FAILGROUP, STATE, HEADER_STATUS FROM V$ASM_DISK ORDER BY GROUP_NUMBER, FAILGROUP, DISK_NUMBER;

第一条告诉你每个磁盘组的冗余类型、总量、剩余空间;第二条告诉你现有盘各属于哪个失败组。为什么要看失败组?NORMAL冗余要求同一个extent的两个副本不能落在同一个失败组里。如果你不加限定地往NORMAL冗余的磁盘组加盘,ASM会按自己的策略把新盘分配到现有失败组,一般也没问题。但如果你一次加了很多盘,希望形成新的失败组来承载更多镜像对,就需要在ADD语句里显式指定FAILGROUP,否则ASM不一定会按你心里想的布局走。

EXTERNAL冗余就简单得多,没有镜像要求,盘加进去直接扩充容量,失败组通常就是每个磁盘自己。HIGH冗余则需要至少三个失败组,扩展时最好成组加,避免整个磁盘组因为失败组数量不足而无法满足冗余要求。这些判断在动手前就应该完成,而不是等命令报错了再回头查。

3. 命令行添加的核心操作:CREATE / ALTER DISKGROUP 用法拆解

3.1 添加磁盘的 SQL 语法逐项说明

实际生产里用得最多的就是这一条:

ALTER DISKGROUP DATA ADD DISK '/dev/oracleasm/disks/ASMDATA09' NAME DATA09;

更完整的写法是这样,带着失败组和power控制:

ALTER DISKGROUP DATA ADD DISK '/dev/oracleasm/disks/ASMDATA10' NAME DATA10, DISK '/dev/oracleasm/disks/ASMDATA11' NAME DATA11 FAILGROUP FGD01 REBALANCE POWER 4;

几个参数值得展开说。NAME是给ASM磁盘组内的磁盘起逻辑名,不写由ASM自动生成;FAILGROUP指定失败组,不指定由ASM安排;REBALANCE POWER指定本次添加触发的重平衡强度,范围受版本和CPU资源影响,Power越大I/O开销越大、完成越快。生产环境如果不想让重平衡立刻抢占大量I/O,可以先把Power设小,之后再用REBALANCE命令调整。

有一个容易忽略的细节:如果磁盘头状态无法自动判定为候选盘,ADD语句会报ORA-15033。这时可以在语句里加FORCE,让ASM忽略磁盘头的部分信息强行加入。但FORCE有明确风险,它可能让ASM错误覆盖还在使用的盘,所以只应在新盘或确认无用的废弃盘上使用,其他场景不要乱加。

3.2 创建磁盘组时怎么“聚合”一片新盘空间

如果需求确实是“新建一个聚合磁盘组”,语法结构变成这样:

CREATE DISKGROUP FRA NORMAL REDUNDANCY FAILGROUP FG1 DISK '/dev/oracleasm/disks/FRA01' NAME FRA01, DISK '/dev/oracleasm/disks/FRA02' NAME FRA02 FAILGROUP FG2 DISK '/dev/oracleasm/disks/FRA03' NAME FRA03, DISK '/dev/oracleasm/disks/FRA04' NAME FRA04;

CREATE DISKGROUP是对一批物理盘做“聚合”的正式入口:它告诉ASM这些盘属于同一个磁盘组,同时规定了镜像冗余级别和失败组边界。创建完成后,存储层看到的就不是一个一个裸盘,而是逻辑上的一个池子。数据库建数据文件、日志文件时只需要指定磁盘组名,至于文件分配到哪块物理盘,由ASM内部管理。

如果是全新环境,创建磁盘组的操作并不难,难在规划失败组。我看到过太多人图方便把所有盘塞进一个失败组,哪怕用的是NORMAL冗余,镜像两份其实都落在同一批物理硬件上,冗余效果约等于零。正确做法是至少把盘按存储框、按机柜、按控制器维度拆开,让同一个extent的两份副本物理隔离,这样省得以后真坏了一个控制器时连镜像一起丢。

3.3 怎么确认重平衡真的跑完了

添加语句执行成功后,至少要看一次重平衡进度和最终磁盘状态。查重平衡用这条SQL:

SELECT GROUP_NUMBER, OPERATION, STATE, POWER, EST_RATE_MBPS, ACTUAL_RATE_MBPS, SOFAR, EST_WORK FROM V$ASM_OPERATION;

输出里的STATE如果是“WAITING”或“RUN”,说明还在重平衡;直到没有记录返回,或者STATE显示“DONE”,重平衡才算完成。再查一次磁盘组空间:

SELECT NAME, TOTAL_MB, FREE_MB, USABLE_FILE_MB FROM V$ASM_DISKGROUP;

如果TOTAL_MB刚好增加了你加进去的容量,盘状态为ONLINE、HEADER_STATUS为MEMBER,就可以放心告诉需求方盘已经到位。很多人在这里拉下检查,第二天发现重平衡还在RUN、数据库I/O很高,才知道命令结束不代表数据搬完。

4. RAC多节点环境下的添加细节

4.1 为什么所有节点都必须识别同一批磁盘

有些环境加盘时只在其中一个节点操作,另一个节点忘了扫盘或忘配UDEV,结果就是ASM实例之间看到的磁盘拓扑不一致,严重时直接报ORA-15032或磁盘组无法挂载。原因在于ASM是集群级组件,每个节点都有自己的ASM实例,磁盘组元数据由所有实例共同维护。盘只在节点A可见、节点B不可见,就相当于这个磁盘组在节点B上“缺胳膊少腿”,ASM的故障检查组关系也会跟着乱。

所以RAC环境的标准流程是:先在所有节点完成OS层的扫描、权限修改和多路径配置,再执行UDEV重载或ASMLib重扫,最后才在ASM实例层面执行添加命令。顺序一旦反了,后续必然要返工。我在现场带人的时候,几乎每次都要求操作者把两个节点的检查结果贴到同一页屏幕里对比确认,再开始下一步。

4.2 双节点实际操作流程

以一个两节点的19c RAC为例,完整流程大致这样。

在节点1上确认OS层可见:

lsblk /dev/sdq /dev/sdr /dev/sds oracleasm listdisks

然后分别在节点1和节点2上执行:

partprobe /dev/sdq /dev/sdr /dev/sds udevadm control --reload udevadm trigger

检查权限:

ls -l /dev/oracleasm/disks/ASMDATA* crw-rw---- 1 grid asmadmin ...

确认权限一致后,从节点1的ASM实例执行添加语句。命令执行完,不要只在一个节点上观察,两个节点的ASM实例都查一下:

crsctl stat res -t

或者直接SQL查询磁盘组状态。RAC环境尤其忌讳把重平衡Power调太高,因为重平衡I/O是跨所有节点的集群级动作,两个ASM实例都会参与,I/O叠加效应比单实例明显。低峰期调到中等Power,白天则保持较小Power,这是比较稳的做法。

5. 常见报错与避坑经验

5.1 报错现象速查表

现象/报错常见原因处理方式
ORA-15032: not all alterations performed批量操作中有一条及以上失败看完整错误堆栈,先解决根因再重跑
ORA-15033: disk is not a candidate盘头状态不对或盘已属于其他磁盘组用kfed read检查盘头;确认无误再使用FORCE或清盘头
ORA-15085: ASM disk name conflicts自定义NAME和其他盘重名换新NAME,或省略NAME让ASM自动生成
ORA-15186: ASMLIB errorASMLib库、权限或设备路径异常检查oracleasm配置、asm_diskstring和/dev/oracleasm权限
设备路径找不到ASM_DISKSTRING未覆盖该路径,或系统还没扫描重扫SCSI总线、覆盖UDEV规则并触发reload
添加后盘OFFLINE盘性能波动或节点间路径不一致查alert日志、多路径状态,修复后执行ONLINE DISK
重平衡长时间不结束Power太低、数据量太大或I/O被持续挤占在低峰期适度提高Power加速完成

表里最容易被忽视的是最后两行。盘OFFLINE不一定代表这块盘物理坏了,更多时候是它在重平衡或抖动期间的I/O响应时间超过阈值,ASM把它踢出在线状态。这时候不要急着拔盘,先看多路径、看存储端口、看OS层的I/O等待。重平衡时间过长也是同理,Power调高只是让I/O更激进,前提是存储后端确实扛得住,别把压力全堆到业务高峰。

5.2 实操习惯:避免在生产环境翻车的几个约定

第一个约定:能一次加多块盘,就不要一块一块加。每执行一次ADD都会触发一次重平衡,一次加8块盘只重平衡一次;拆成8次加,等于让生产库的I/O被反复折腾。现场如果存储侧已经把盘都映射好了,尽量在一条语句里把同一批盘全部添加。

第二个约定:加盘前先记录当前基准。比如查一下V$ASM_OPERATION有没有历史堆积,看下AWR里的I/O基线,加完后过一小时再对比,及时发现异常。很多问题不是命令报错,而是重平衡带来的长期性能损耗,没有基线很难判断。

第三个约定:不要轻易把不同转速、不同型号的盘混在同一个失败组里。NORMAL或HIGH冗余下,一个失败组的性能和容量往往决定磁盘组的下限,慢盘会拖住所有镜像副本的写入。这个规则在“聚合磁盘”场景同样成立:新盘容量和旧盘差异太大,重平衡后可能出现容量水桶效应,ASM会尽量均衡容量,但总空间分配不会按物理容量百分之百跑满。

6. 一次完整添加操作的现场复盘

6.1 环境信息与动手前的判断

用某个项目的生产环境举个例子(信息已脱敏):双节点RAC,Oracle 19c,DATA磁盘组NORMAL冗余,原有12块盘,分在两个失败组FG1和FG2,当前可用空间约占60%。存储团队新挂了8块盘,需要加入DATA组扩容。因为新盘类型和旧盘接近,现场决定让它们均匀分布到FG1和FG2,避免集中到某一个失败组导致冗余布局失衡。

动手前先做三道确认:所有节点OS能看见8块盘;权限统一为grid:asmadmin;盘头未被旧数据污染。确认没问题后,在节点1的ASM实例里把8块盘的ADD语句组织成一次操作。注意,这一步我刻意不看图形界面,全走命令行,因为命令行日志留痕清晰,出了事能追溯。

6.2 从扫描盘到重平衡完成的命令记录

节点A上执行:

ls /dev/oracleasm/disks/ ASMDATA13 ASMDATA14 ASMDATA15 ASMDATA16 ASMDATA17 ASMDATA18 ASMDATA19 ASMDATA20

节点B同样执行,确认返回一致。然后分别在两个节点上:

udevadm control --reload udevadm trigger

进入ASM实例执行添加:

ALTER DISKGROUP DATA ADD DISK '/dev/oracleasm/disks/ASMDATA13' NAME DATA13 FAILGROUP FG1, DISK '/dev/oracleasm/disks/ASMDATA14' NAME DATA14 FAILGROUP FG2, DISK '/dev/oracleasm/disks/ASMDATA15' NAME DATA15 FAILGROUP FG1, DISK '/dev/oracleasm/disks/ASMDATA16' NAME DATA16 FAILGROUP FG2, DISK '/dev/oracleasm/disks/ASMDATA17' NAME DATA17 FAILGROUP FG1, DISK '/dev/oracleasm/disks/ASMDATA18' NAME DATA18 FAILGROUP FG2, DISK '/dev/oracleasm/disks/ASMDATA19' NAME DATA19 FAILGROUP FG1, DISK '/dev/oracleasm/disks/ASMDATA20' NAME DATA20 FAILGROUP FG2;

执行完立刻查重平衡:

SELECT OPERATION, STATE, POWER, EST_WORK, SOFAR, EST_RATE_MBPS FROM V$ASM_OPERATION;

当时输出大致是:

REBAL RUN 8 386000 1200 40

这表示重平衡正在跑。因为是在低峰期操作,Power设在8,观察最终没有新的V$ASM_OPERATION记录后,再做一次验证:

SELECT NAME, TOTAL_MB, FREE_MB, USABLE_FILE_MB FROM V$ASM_DISKGROUP WHERE NAME='DATA';

TOTAL_MB比原来增加了约2400000MB(8块300G盘按ASM容量计算),8块新盘HEADER_STATUS都是MEMBER,STATE为ONLINE。到这里,这次操作才算真正落地。任何变更日志只写到“SQL执行成功”都算半截,必须加上重平衡完成和磁盘状态验证。

7. 添加完之后,我习惯顺手做的几件事

7.1 记录与归档

即便重平衡已经完成,我也不会急着关终端。当次的盘符、设备路径、新建的ASM磁盘名、FAILGROUP划分、添加日期,全部记到变更文档里。很多环境半年后排查存储时,发现某个失败组的盘数量不对称,靠的就是这些记录。只看V$ASM_DISK能看到的是现状,看不到的是当时的规划意图,所以文档必须写清楚为什么这样分。

另外,ASM磁盘组的元数据有备份价值。如果环境允许,我会顺手把当前磁盘组配置导出一份:

SELECT NAME, FAILGROUP, PATH FROM V$ASM_DISK;

留着以后排查或者做环境克隆时用,省事不少。

7.2 后续观测

添加完盘的24小时内,重点观察两件事:一是重平衡是否真的结束,二是加盘后数据库的I/O有没有明显波动。如果用了很低的重平衡Power,可能出现“看似结束,第二天又继续跑”的情况。ASM会把重平衡操作分成多个批次,V$ASM_OPERATION里偶尔会出现新纪录,不用慌,确认Power设置和I/O等待合理即可。

另一个观察点是磁盘组的空间分布。新盘容量如果和旧盘差异比较大,重平衡后个别盘可能接近写满,这时需要主动调整数据文件布局或再一次做extent迁移。我个人在实际操作中的体会是,命令行方式加盘并不难,难的是把“加盘”当成一次完整的存储变更来对待:准备、执行、验证、记录,一个环节都不能省。尤其是RAC环境,多节点一致性永远是第一优先级,任何只在一台机器上确认的动作,都等于没确认。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询