ASM 磁盘加减实战:怎样证明数据已经安全迁移
凌晨一点,存储同事在群里问:
"ASM 里的旧盘已经 drop 了吧?我现在能从存储端回收吗?"
DBA 看了一眼终端:
ALTER DISKGROUP DATA DROP DISK DATA_0002;
Diskgroup altered.
从字面看,一切顺利。但如果这时回答"可以",风险就来了。
因为 Diskgroup altered. 只说明 Oracle ASM 已接受这次变更请求;它并不说明旧盘上的 extent 已全部迁出,更不说明旧盘已可安全断开。
ASM 磁盘加减最重要的问题,从来不是"命令怎么敲",而是:
怎样证明数据已经安全迁移,旧盘可以被回收?
答案不是单一命令,而是一条完整的证据链。
一、先纠正一个误区:DROP 不是立即删除
执行:
ALTER DISKGROUP DATA DROP DISK DATA_0002;
ASM 会做两件事:
- 将该磁盘标记为待移除;
- 通过 rebalance,把原先位于该磁盘上的文件 extent 迁移到磁盘组中的其他磁盘。
这是一项后台工作。默认情况下,ALTER DISKGROUP 不会等待 rebalance 完成就把控制权交还给用户。
因此,下面这句话必须记住:
SQL 返回成功
≠ rebalance 已完成
≠ 数据已经迁走
≠ 旧盘可安全拔除
从内部机制看,DROP DISK 只是把这块盘的成员身份置为待移除,并触发 ASM 的重新均衡。真正决定这块盘"能不能被外部回收"的,是磁盘头(disk header)里的状态字段。ASM 磁盘的磁盘组信息、磁盘状态(kfdhdb.hdrsts)都保存在磁盘盘头上,而不是只存在于内存或控制文件里。也就是说,判定依据落在这块物理盘自己身上——这正是我们能做"终态核验"的基础。
Oracle 官方明确要求:在待删除磁盘的 V$ASM_DISK.HEADER_STATUS 变为 FORMER 之前,不要复用、移除或断开该磁盘。
这也是全文最核心的结论。
二、加盘、减盘之前,先做"能不能迁"的评估
减盘不是简单地让磁盘组少一块盘。它的本质是:剩余磁盘必须能够接住待移除磁盘上的数据,同时仍满足磁盘组冗余和 failure group 的保护要求。
操作前,先查看磁盘组容量与冗余余量:
SELECT name,
type,
state,
total_mb,
free_mb,
required_mirror_free_mb,
usable_file_mb
FROM v$asm_diskgroup
WHERE name = 'DATA';
重点不是只看 FREE_MB:
FREE_MB:当前空闲容量;REQUIRED_MIRROR_FREE_MB:为应对故障、维持镜像冗余而保留的空间;USABLE_FILE_MB:在考虑冗余需求后,可安全提供给文件使用的空间。
对于 NORMAL 或 HIGH 冗余磁盘组,还要确认待移除磁盘所在的 failure group。剩余空间"总量足够",不代表每个 failure group 都能满足镜像放置要求。
这一点在 12.1.0.2 之后的版本尤其重要:ASM 引入了对 failure group 个数、磁盘大小、磁盘个数的检查。例如 normal 冗余磁盘组的常规故障组少于 3 个、或 high 冗余少于 5 个时,直接 drop disks in failgroup 会被拒绝,报出:
ORA-15067: command or option incompatible with diskgroup redundancy
-- 或 19c 及以后
ORA-15032: not all alterations performed
ORA-59327: Dropping more fail groups is not allowed with disk group redundancy
如果此时用 FORCE 强行删除,虽然删除"成功",但 rebalance 阶段会因为不满足故障组数据要求而失败,报 ORA-59048,同时磁盘进入 forcing 状态、alert 日志出现告警。这说明"命令成功"和"迁移成功"是两件事,在 failure group 场景里尤其明显。
再核对待操作的磁盘,避免因名称相似而误操作:
SELECT group_number,
disk_number,
name,
failgroup,
path,
mount_status,
mode_status,
state,
header_status,
total_mb,
free_mb
FROM v$asm_disk
WHERE group_number = (
SELECT group_number
FROM v$asm_diskgroup
WHERE name = 'DATA'
)
ORDER BY disk_number;
在变更单里,至少应明确记录:磁盘组名、ASM 磁盘名、存储设备路径、failure group、容量、操作人和回退方案。
三、最佳实践:加盘和减盘尽量放在一次变更里
如果目标是替换旧盘,而不是单纯缩容,推荐在一条 ALTER DISKGROUP 中完成 add 和 drop:
ALTER DISKGROUP DATA
ADD DISK '/dev/asm/data_0007' NAME DATA_0007
DROP DISK DATA_0002
REBALANCE POWER 8 WAIT;
这样做有三个好处:
- ASM 在同一次 rebalance 中完成数据重新分布,减少不必要的数据搬运;
- 新盘先加入,给数据迁移提供了明确落点;
- 更容易避免"先 drop,后发现剩余空间不足"的尴尬。
Oracle 也建议在可能时将 add 与 drop 放到同一条 ALTER DISKGROUP 中,以减少 rebalance 次数,并帮助确保迁移有足够空间完成。
WAIT 对脚本特别有价值:它会让当前会话等待 rebalance 完成后再返回。但请注意:即使使用了 WAIT,仍应执行最终状态核验。 发生异常时,不能仅以客户端命令结束作为安全依据。
一个值得借鉴的"整盘替换"套路
当目标是把 ASM 从一个磁盘集整体迁移到另一个磁盘集时,业界经典做法是"在线逐步替换":
- 逐个添加新磁盘,且每次都用 power level 0(此时不触发 rebalance)——不要一条命令里加一堆盘,否则容易把磁盘组锁死;
- 逐个 drop 掉除最后一块之外的所有旧盘,同样用 power level 0;
- 最后一块旧盘用 power level > 0 删除,此时才真正触发 rebalance——新盘开始承接从旧盘迁出的 allocation unit,旧盘逐步清空并在完成后被彻底删除。
这套方法的优点是:只发生一次 rebalance,效率高,且全程磁盘组可访问、无需停机;缺点是无法借此改变冗余级别(要改冗余只能走离线重建路径)。这个"只在最后一步触发 rebalance"的思路,和前面"add/drop 放一条命令"的思路本质相同——都是为了把数据搬运压缩到最少次数、并在搬运前先备好落点。
四、迁移过程中看什么:V$ASM_OPERATION 是进度表,不是放行单
执行 add/drop 后,先观察 rebalance:
SELECT group_number,
operation,
state,
power,
sofar,
est_work,
est_rate,
est_minutes
FROM v$asm_operation;
常见关注点:
OPERATION:通常可看到REBAL;在新版本中还会分COMPACT、REBALANCE、REBUILD、RESYNC等多个 PASS 阶段;STATE:确认操作是否在运行、等待(WAIT)或异常(ERRS);SOFAR / EST_WORK:当前工作量与估算总工作量;EST_RATE:估算处理速率;EST_MINUTES:估算剩余时间;ERROR_CODE:若某阶段STATE = ERRS,这里会给出错误码(例如前面提到的ORA-59048)。
如果业务高峰到来,rebalance 影响过大,可以调整正在执行的 power:
ALTER DISKGROUP DATA REBALANCE MODIFY POWER 4;
POWER 本质上控制 rebalance 的并行度与资源消耗。数值越高,迁移通常越快,但对 I/O、CPU 和业务延迟的压力也越大。不要把它当成"越大越好"的参数。
这里有两个高频坑:
坑一:power 0 容易把自己"锁住"。 如果曾执行过 ALTER DISKGROUP ... MODIFY POWER 0,rebalance 会被暂停;之后再想用 REBALANCE POWER 6 启动时,可能发现 ARB/RBAL 进程毫无反应,V$ASM_OPERATION 里各阶段 STATE = WAIT 且 POWER = 0。这类问题通常不是命令写错,而是磁盘组内部的 partner slot 结构达到上限(例如报 kfgpGet insufficient space、KFPTNR_MAXTOT),需要通过 offline/online 相关磁盘等手法绕过一致性检查后,rebalance 才会恢复。排查时不要只盯命令,要看 alert 日志和 V$ASM_OPERATION 的完整状态。
坑二:Ctrl+C 不等于取消。 终端可能返回,但 rebalance 并不会因此自动取消;需要继续检查其实际状态。此时 ASM COD ROLLBACK OPERATION COMPLETION 这类等待事件可能长时间出现——它表示 ASM 正在等待 Continuing Operations Directory 中记录的回滚操作完成,常见于磁盘组操作中断或 rebalance 中断场景。它本身是保护机制,但长时间停留就说明有操作没干净收尾,必须查清。
五、真正的放行标准:HEADER_STATUS = FORMER
当 V$ASM_OPERATION 中不再看到该磁盘组的 rebalance 记录时,说明后台迁移看起来结束了。但这只是第一层证据。
真正决定旧盘是否能被存储团队回收的,是下面这条查询:
SELECT name,
path,
state,
mode_status,
header_status
FROM v$asm_disk
WHERE path = '/dev/asm/data_0002';
理想结果是:
HEADER_STATUS = FORMER
要理解为什么是 FORMER,需要先认识 HEADER_STATUS 的完整取值。它是每个实例对磁盘发现结果的状态描述:
| HEADER_STATUS | 含义 |
|---|---|
UNKNOWN |
磁盘头尚未读取 |
CANDIDATE |
磁盘不属于任何磁盘组,可通过 ALTER DISKGROUP 添加 |
PROVISIONED |
同样可添加,但管理员已完成平台特定操作(如 asmtool/asmlib),磁盘已对 ASM 可用 |
MEMBER |
磁盘已是现存磁盘组成员,不应再加入其他磁盘组,除非指定 FORCE |
FORMER |
磁盘曾属于某磁盘组但已被干净地删除,可加入新磁盘组 |
CONFLICT |
因冲突导致磁盘未挂载 |
FOREIGN |
磁盘包含非 ASM 的 Oracle 数据(数据文件、日志、OCR 盘等) |
INCOMPATIBLE |
磁盘头版本与 ASM 软件版本不兼容 |
FORMER 表示 ASM 已经清除了该盘作为当前磁盘组成员的身份信息,它不再是该磁盘组的活动成员。Oracle 对此给出的安全边界非常明确:当 HEADER_STATUS 变为 FORMER 后,磁盘才可以复用、移除或断开。
相反,如果仍看到:
STATE = DROPPING
HEADER_STATUS = MEMBER
那么结论只有一个:不要拔盘,不要回收,不要在存储端重新分配 LUN。
补充一个工程化的核验手段:由于磁盘状态同时记录在盘头的
kfdhdb.hdrsts字段上,必要时可用kfed read直接读取盘头,与V$ASM_DISK相互印证。当视图结果与现场现象不一致时,盘头才是最终事实。
六、一套可交付的"安全迁移证据链"
一次成熟的 ASM 减盘操作,建议至少留存以下五项证据。
| 阶段 | 要保留的证据 | 证明什么 |
|---|---|---|
| 变更前 | V$ASM_DISKGROUP 容量与冗余信息 |
剩余磁盘具备承接能力 |
| 变更前 | V$ASM_DISK 的磁盘名、路径、failure group |
操作对象准确无误 |
| 迁移中 | V$ASM_OPERATION 截图或采样记录 |
rebalance 正在正常推进 |
| 迁移后 | V$ASM_OPERATION 无该磁盘组任务 |
rebalance 已结束 |
| 最终放行 | 待移除磁盘 HEADER_STATUS = FORMER |
旧盘可安全回收 |
如果要再加一层稳妥性,可以在迁移完成后检查磁盘组元数据一致性:
ALTER DISKGROUP DATA CHECKALL;
该命令用于检查 ASM 磁盘组元数据内部一致性。它不是每次普通换盘都必须执行的"完成标志",但在重要生产变更、异常恢复后或你怀疑元数据存在问题时,是有价值的附加验证。
如果希望从 extent 层面做更细的核实,还可以借助内部视图 X$KFFXP(ASM extent 映射)核对某个 ASM 文件的 extent 分布在哪些磁盘上,用"数据实际落在哪里"来反证旧盘确实已被清空。这属于进阶手段,日常变更用前面五项证据即可。
七、遇到风险时,怎么停下来?
如果发现选错了盘,或者迁移还在进行时需要中止计划,不要直接在存储端断开设备。
对于尚未完成的非 FORCE drop,可以使用:
ALTER DISKGROUP DATA UNDROP DISKS;
它用于取消磁盘组内仍处于 pending 状态的 drop 操作。但要注意两个边界:
- drop 已完成后,不能再靠
UNDROP DISKS恢复。 ASM 磁盘不会进入类似回收站的地方,如果 drop 已经彻底完成,唯一的恢复方式是重新ADD DISK把它加回来。 DROP DISK ... FORCE的风险更高。 它适用于 ASM 已无法读写目标盘等故障场景,会让 ASM 依赖剩余镜像副本重建数据;在 rebalance 完成前,数据保护可能处于降低状态。
因此,健康磁盘的计划性迁移应优先使用默认的 NOFORCE 路径。外部冗余(EXTERNAL REDUNDANCY)磁盘组不能使用 FORCE drop,因为没有 ASM 镜像副本可供重建。
关于 FORCE 还有一个细节:当一块盘处于 MEMBER 状态、但不属于任何已挂载的磁盘组时,可以用 FORCE 强制把它加入;而对于 FOREIGN 状态的盘,也只能用 FORCE 添加。这说明 FORCE 是一把针对异常状态的钥匙,而不是为了省时间的常规选项。
八、最常见的四个错误动作
1. 看到"Diskgroup altered"就通知存储回收。
这是最危险的误解。命令提交成功,不等于 extent 已经迁完。
2. 只盯 V$ASM_OPERATION,不查 HEADER_STATUS。
V$ASM_OPERATION 告诉你迁移有没有在跑、估计还要多久;HEADER_STATUS = FORMER 才是旧盘可回收的最终状态证据。
3. 只看 FREE_MB,不看冗余与 failure group。
尤其是 NORMAL/HIGH 冗余环境,容量判断必须结合 REQUIRED_MIRROR_FREE_MB、USABLE_FILE_MB 与 failure group 布局。12.1.0.2 之后还有 failure group 个数/大小检查,强行 FORCE 可能换来一个 ORA-59048。
4. 计划性迁移也使用 FORCE。
FORCE 是故障处理工具,不是为了省时间的常规选项。它会增加 rebalance 期间的风险暴露。
九、一个容易被忽略的"隐藏风险":镜像副本的沉默损坏
减盘、换盘本质上是数据搬运,而搬运前后都依赖镜像冗余的保护。这里有一个容易被忽略的细节:在 NORMAL/HIGH 冗余下,主副本(Primary block)损坏可由镜像副本(Secondary block)自动修复;但如果只有镜像副本损坏,dbv、RMAN、普通 DB SQL 默认都只读主副本,不会读镜像副本,因此既无报错、也无感知。
这意味着:你在做磁盘迁移时,磁盘组表面上"很健康",但某些 extent 的镜像副本可能早已损坏。一旦迁移过程中主副本出问题,才发现没有可用的镜像可回退。
因此,在重要生产变更(尤其是涉及减盘、换盘)前,如有条件,应主动对 ASM 做一致性/坏块扫描,而不要假设"冗余在 = 数据一定安全"。这正是 CHECKALL 这类元数据校验,以及 scrub 类主动检查手段的价值所在。
结尾:安全不是一句"迁移完成",而是一组可验证状态
ASM 的价值,在于可以在线完成磁盘增删和数据重新均衡。但它的安全边界也很清晰:ASM 负责搬迁数据,DBA 负责证明搬迁已经完成。
下次存储同事问"这块盘能不能回收"时,不要回答"SQL 已经执行了"。请把答案换成:
V$ASM_OPERATION已无该磁盘组的 rebalance;待移除磁盘的HEADER_STATUS已确认是FORMER;容量、冗余与元数据检查均正常。可以安全回收。
这才是一份可以交付、可以复盘、可以经得起存储团队签字的安全结论。
附:核心证据清单(可直接抄进变更模板)
| 序号 | 检查项 | 命令要点 | 通过标准 |
|---|---|---|---|
| 1 | 容量与冗余余量 | v$asm_diskgroup |
usable_file_mb 充足,failure group 布局满足要求 |
| 2 | 操作对象核对 | v$asm_disk(含 failgroup、path) |
磁盘名/路径/故障组与变更单一致 |
| 3 | 迁移进度 | v$asm_operation |
state 正常推进,error_code 为空 |
| 4 | 迁移结束 | v$asm_operation |
无该磁盘组 rebalance 记录 |
| 5 | 最终放行 | v$asm_disk.header_status |
FORMER |
| 6 | 元数据一致性(可选) | ALTER DISKGROUP ... CHECKALL |
无错误 |
| 7 | 盘头交叉验证(可选) | kfed read 的 kfdhdb.hdrsts |
与视图一致 |
本文基于 Oracle ASM 官方文档与知识库中的相关 MOS 资料、实践案例整理,涉及版本差异(如 12.1.0.2 起引入的 failure group 检查、多 PASS rebalance 状态)时请以目标环境实际版本为准。所有查询语句请在目标实例中先用只读方式验证后再用于生产变更。
浙公网安备 33010602011771号