
手头正好接到一个存储替换的活老的存储阵列要下电退役上面挂的ASM磁盘组全是Oracle数据文件业务还不能长时间停。按照常规思路要么用expdp导出导入要么用存储层的LUN复制做冷迁移但前者时间窗口根本不够后者又牵扯到卷映射变更和中间状态校验。最后我选了ASM最经典的玩法——通过rebalance把磁盘数据从旧盘“平滑”到新盘上整个过程对数据库层面完全透明数据文件路径、ASM别名一概不用改。这篇文章就围绕这套操作展开适合正在做存储替换、磁盘扩容、或者单纯想把ASM磁盘组从一组物理盘挪到另一组物理盘的朋友参考。文章会讲rebalance的底层原理、操作步骤、参数怎么定以及我实际踩过的坑。1. 为什么选rebalance做磁盘迁移1.1 磁盘迁移的几种方案对比遇到磁盘迁移需求很多DBA脑子里第一反应是数据泵导出导入。逻辑迁移确实能跨平台、跨版本甚至能把数据从Oracle搬到其他数据库但在这类“存储替换”场景里它并不是最优解。数据泵要经过逻辑解析和SQL重放全库导出导入的时间通常是物理迁移的3到5倍而且源库端的业务对象、序列、物化视图、同义词等元数据多多少少都有重建成本稍不注意就漏掉对象。第二种方案是干脆停库把数据文件直接拷贝到新磁盘上再改ASM磁盘组或者用文件系统管理。这种方式逻辑上最简单但问题在于停机窗口。现在业务部门给DBA的窗口经常只有两三个小时几百GB的小库还好说碰上几个TB的大库裸拷贝的时间根本不够。而且一旦文件拷贝过程中出现中断整个一致性就泡汤了恢复起来非常痛苦。所以在这类场景下ASM的rebalance就显出价值了。它属于在线物理级的数据重分布不需要停库不需要改数据库端的任何配置。你只需要向磁盘组里增加新磁盘再删除旧磁盘ASM会在后台自动把数据块从旧盘搬移到新盘。数据库完全感知不到存储路径的变化所有数据文件、控制文件、日志文件的ASM别名保持原样这对业务连续性来说是最友好的。1.2 先确认存储架构和冗余策略动rebalance之前第一件事不是敲命令而是先摸清磁盘组的冗余架构。ASM磁盘组有三种冗余类型EXTERNAL外部冗余通常由存储阵列做RAID、NORMAL两副本、HIGH三副本。冗余类型直接决定了迁移过程中的风险和空间要求。如果磁盘组是EXTERNAL冗余意味着ASM本身没有做镜像一块盘损坏数据就丢。这种架构下做rebalance迁移新盘加进来之后数据会从旧盘拷贝到新盘这个过程中旧盘如果出现故障数据是不可恢复的。所以我通常会建议EXTERNAL冗余的磁盘组在执行迁移前一定要做一次全量备份最好是image copy级别的备份或者确保存储阵列层面有可靠的快照。对于NORMAL和HIGH冗余的磁盘组情况会好很多。ASM天然会在不同failgroup里保留副本迁移过程中即使某个旧盘挂了只要还有一份完整副本在磁盘组可以继续工作rebalance也能继续推进。但这里面有个容易忽略的点很多环境里虽然磁盘组是NORMAL冗余但所有物理盘都在同一个存储阵列里所谓failgroup分离并没有体现到硬件级别的容灾上。这种时候我建议把每个物理存储LUN单独划成一个failgroup这样rebalance在搬数据的时候才会真正把副本打散到不同的物理设备上。查看磁盘组冗余类型的命令很简单用grid用户登录ASM实例执行SELECT name, type, total_mb, free_mb, required_mirror_free_mb, usable_file_mb FROM v$asm_diskgroup;type字段直接显示EXTERN、NORMAL或HIGH。需要注意的是required_mirror_free_mb这个字段它表示ASM为了保证冗余度而必须保留的镜像空间。在后续估算删除旧盘所需空间时这个值是重要的参考。2. rebalance到底做了什么2.1 核心后台进程与工作流rebalance不是虚无缥缈的“自动平衡”它背后是一套完整的过程协作机制。ASM实例里有两个关键后台进程RBAL和ARBx。RBAL是rebalance的协调者负责监控磁盘组的变化、生成rebalance计划、把任务分解并分发给ARB进程。ARB0到ARBn是实际干活的进程数量由POWER参数决定它们负责把extent从源盘读取、再写入目标盘。从工作流来看rebalance分两个阶段。第一阶段叫“规划”RBAL进程根据磁盘组的现有分布、各盘剩余空间、failgroup配置计算出一份数据移动计划说白了就是哪些extent需要从哪块盘挪到哪块盘。第二阶段是“执行”ARB进程按计划逐块搬移每搬完一个extent就更新一次元数据指针数据库访问到这部分数据时会通过ASM的元数据层自动定位到新位置整个过程对数据库完全透明。还有一个容易忽略的点是rebalance不仅发生在你主动执行ADD或DROP磁盘时。如果某块盘发生性能抖动或者读写延迟异常ASM也可能自动触发轻量级的rebalance来重新打散数据。所以有时候你什么都没做v$asm_operation里却能看到REBAL操作就是这个原因。2.2 POWER参数是怎么影响速度的ASM rebalance的速度由POWER参数控制。这个参数的作用是控制同时运行的ARB进程数量取值为0到11值越大并行度越高搬移速度越快但带来的IO压力也越大。POWER参数有两个层面的设定方式。一个是实例级参数ASM_POWER_LIMIT可以通过以下命令查看和修改SHOW PARAMETER ASM_POWER_LIMIT; ALTER SYSTEM SET ASM_POWER_LIMIT5 SID*;另一个是语句级的REBALANCE POWER子句比如ALTER DISKGROUP data ADD DISK /dev/mapper/data05 REBALANCE POWER 8;语句级的POWER优先级高于实例级参数。也就是说即使实例级ASM_POWER_LIMIT设的是3如果在ADD语句里指定了POWER 8这次rebalance就会按8的并行度执行。实际项目里我一般的建议是如果业务处于高峰时段POWER设在2到3之间保证rebalance不抢太多IO如果业务低谷或者停机维护窗口可以拉到6到8POWER 10到11是给那种“赶紧搬完别的都不管”的场景用的比如整阵列迁移。这里有个误区很多人觉得POWER越大越好其实不是。ARB进程越多对ASM实例的SGA内存和CPU消耗也越大如果底层存储IO本身就存在瓶颈POWER开太高反而可能引起数据库性能直线下降甚至出现IO hang。2.3 rebalance过程中潜在风险rebalance虽然在线、透明但风险点也不少提前了解才能提前规避。第一是IO双倍压力。rebalance执行期间老数据还在对外提供服务新数据的搬移又在不断读取和写入整个存储系统的IO压力会明显上升。如果底层存储本身IOPS余量不多业务端就可能出现延迟飙升甚至TTL超时。第二是空间妥协风险。加新盘的空间需求相对可控真正要注意的是删老盘的阶段。删盘时ASM会把老盘上的所有extent在其他盘上重建一份这就要求磁盘组剩余空间至少要大于等于老盘当前已经使用的数据量。空间不够的话rebalance会一直卡在某个状态甚至报ORA-15032或ORA-15041错误。第三是ASM实例重启的风险。rebalance过程中如果ASM实例意外重启操作一般会在ASM恢复后继续但复杂环境下可能出现rebalance与挂载、磁盘offline等状态交叉处理起来会麻烦不少。所以正式执行前最好先确认ASM实例的稳定性比如检查alert日志有没有ORA-600、内存问题等隐患。还有一个容易忽略的地方是磁盘组空间利用率。rebalance时ASM会优先把数据分配到可用空间多的盘上如果你加进来的新盘和其他旧盘容量差距很大比如新盘2TB旧盘全是300GB新盘加进来后几乎所有数据都会优先往新盘上搬最终导致新盘很快就满了其他盘还是很空。这种情况在数据库后续扩容时会造成严重的空间不均所以条件允许的情况下尽量让同一组磁盘的容量接近。3. 实操过程从准备到切换3.1 迁移前环境检查动手之前先把环境信息摸清楚。我习惯先列一张检查清单包含以下几个方面磁盘组冗余类型、各盘容量和路径、ASM实例版本、当前ASM_POWER_LIMIT值、告警日志是否干净、数据库端有无异常任务。以grid用户登录ASM实例查看磁盘组和磁盘状态SELECT name, group_number, state, type, total_mb, free_mb FROM v$asm_diskgroup; SELECT group_number, disk_number, name, path, failgroup, total_mb, free_mb, state, mode_status, mount_status FROM v$asm_disk ORDER BY group_number, disk_number;这里重点看三列state是否都是NORMALmode_status是否都是ONLINEmount_status是否都是CACHED。如果发现某块盘是OFFLINE或者UNKNOWN先不要动其他盘先处理这块盘的异常否则rebalance执行到一半可能出现不可预料的后果。再看一眼asm_diskstring参数确保新盘的路径能被ASM自动扫描到SHOW PARAMETER ASM_DISKSTRING;如果磁盘是通过udev规则映射到/dev/mapper/下的通常设为/dev/mapper/asm-*这种通配符形式。如果ASM使用的是ASMLib则对应ORACLEASM_DISKSTRING。新盘接入操作系统的步骤这里简单说一下。存储端划分好LUN并映射给主机后在操作系统层面通过multipath -ll确认多路径设备已经识别例如新盘对应/dev/mapper/asm-data05。然后需要给磁盘打上持久化标签并在udev规则里绑定好权限确保grid用户能够读写这个设备。我见过不少新盘加入后ASM识别不到的情况绝大多数都是因为udev规则没生效或者权限不对所以这一步一定不要偷懒。配置完udev规则后记得执行udevadm control --reload还有udevadm trigger让规则生效然后再去ASM实例里扫描。扫描新盘进ASM可以在SQLPLUS里执行ALTER SYSTEM DISK SCAN ALL;或者用asmcmd的命令asmcmd scandisks扫描完之后再次检查v$asm_disk视图确认新盘已经以candidate状态出现并且header_status不是FORMER或者FOREIGN。3.2 执行rebalance迁移环境确认没问题就可以正式开始迁移了。我的习惯是先把新盘全部加到磁盘组等待rebalance完成再做旧盘的删除而不是新旧盘交替进行。这样做的好处是ADD阶段磁盘组空间只会增加不会减少即使旧盘在过程中出问题风险也相对可控。把新盘加入DATA磁盘组示例命令如下ALTER DISKGROUP data ADD DISK /dev/mapper/asm-data05 NAME data_005 REBALANCE POWER 5; ALTER DISKGROUP data ADD DISK /dev/mapper/asm-data06 NAME data_006 REBALANCE POWER 5; ALTER DISKGROUP data ADD DISK /dev/mapper/asm-data07 NAME data_007 REBALANCE POWER 5;注意每块盘都显式指定了NAME这是为了避免ASM自动生成一串难以识别的磁盘别名后续在DROP的时候直接按名字操作不容易弄错。ADD操作提交后rebalance立刻开始。查看进度SELECT group_number, operation, state, power, sofar, est_work, est_minutes FROM v$asm_operation;字段含义sofar表示已经完成的rebalance工作量est_work是预估总工作量est_minutes是预估剩余分钟数。当state显示为COMPACT时说明正在做压缩和整理这是rebalance收尾阶段的正常现象不需要干预。等rebalance全部完成再执行旧盘删除ALTER DISKGROUP data DROP DISK data_001 REBALANCE POWER 5; ALTER DISKGROUP data DROP DISK data_002 REBALANCE POWER 5; ALTER DISKGROUP data DROP DISK data_003 REBALANCE POWER 5;如果担心同时删除多块盘导致空间压力太大可以一次删除一块等rebalance完成后再删下一块。不过一次删一块的弊端是总迁移时间会线性拉长且每一次rebalance都是全量重分布效率反而低。我在实际生产环境里只要空间估算确认过一般会一次性把同一批旧盘都DROP掉让ASM统一调度。删除完成后再次检查磁盘组和磁盘状态确认旧盘已经从v$asm_disk中消失磁盘组所有盘都已ONLINE且各盘的FREE_MB相对均匀。3.3 迁移过程业务影响控制rebalance最怕的不是慢而是对业务产生不可接受的性能冲击。我的经验是分三层来控制。第一层是POWER值。默认情况下如果不在语句里显式指定POWER就会用实例级ASM_POWER_LIMIT。为了保证每次rebalance都能按预期速度执行我会在ADD和DROP语句里都显式带上REBALANCE POWER参数。第二层是执行时机。即便用了POWER 5在业务高峰时段执行大规模rebalance仍然可能导致存储IOPS被打满。所以我会提前和业务方确认低峰窗口一般是凌晨两三点把ADD和DROP操作都安排在这个窗口内执行。第三层是实时监控。rebalance执行期间我一般每隔五到十分钟查一次v$asm_operation和存储端的性能监控看到磁盘utilization持续超过85%或者数据库等待事件出现明显异常就把power调低一档。POWER是可以动态调整的不用取消rebalance直接改实例级参数配合语句级命令ALTER DISKGROUP data REBALANCE POWER 3;这条命令可以在不中断rebalance的前提下把当前及后续阶段的并行度调低。3.4 验证与切换rebalance完成后不能拍拍屁股就走要做一轮完整验证。第一步确认v$asm_operation里没有任何正在执行的REBAL操作记录。第二步检查磁盘组整体状态SELECT name, state, total_mb, free_mb, usable_file_mb FROM v$asm_diskgroup;第三步确认数据库端无感知。登录数据库实例执行SELECT name, file#, status FROM v$datafile; SELECT name, status FROM v$controlfile; SELECT group#, status, type FROM v$log;这些都显示正常说明数据库的数据文件和控制文件访问都没有问题。第四步确认ASM告警日志里没有异常错误。告警日志位置可以通过asmcmd alert快速定位。确认无误后就可以在操作系统层面把旧盘从存储映射中解绑删除对应的udev规则清理multipath配置。这一步我也吃过亏旧盘如果还残留在操作系统上下次ASM扫描磁盘时有可能把它当作candidate盘扫进来一旦误加到某个磁盘组后果非常严重。4. 常见问题与排查实录4.1 rebalance进度一直卡着不动rebalance最让人焦虑的现象就是进度条不走。v$asm_operation里sofar一直没有增长est_minutes还在不停变大或者干脆报错退出。遇到这种情况第一步看磁盘组的空间。用SELECT name, total_mb, free_mb, required_mirror_free_mb FROM v$asm_diskgroup;对比需要删除的旧盘容量如果free_mb减去required_mirror_free_mb后的可用空间小于旧盘当前数据量rebalance就极容易卡住。解决办法是再加一块新盘进来扩容或者降低删除磁盘的规模。第二步看磁盘状态。如果某块旧盘处于OFFLINE状态而它上面还有extent没有搬完rebalance就会一直等待。用SELECT name, state, mode_status, mount_status FROM v$asm_disk;发现有OFFLINE的盘先执行ALTER DISKGROUP data ONLINE DISK data_00N;把盘恢复在线再观察rebalance是否继续。第三步看alert日志。ASM的alert日志会记录rebalance暂停或失败的具体原因比如ORA-15041磁盘空间不足或者ORA-15085磁盘组已满。4.2 新盘加入后状态UNKNOWN或无法识别新盘加入磁盘组后v$asm_disk里显示UNKNOWN或者扫描后根本看不到新盘这类问题大多出在操作系统层。最常见的是权限问题。ASM进程要以grid用户身份读写磁盘设备如果udev规则没有给对权限磁盘就只能看到设备节点而打不开。检查/dev/mapper/asm-data05的属主和权限确认owner是gridgroup是asmadminmode是660。另一个是路径识别问题。ASM_DISKSTRING设置的是/dev/mapper/asm-*而新盘在multipath里生成的设备名不在这个通配符范围内扫描就看不到。解决办法是把新盘的别名规范好统一命名。还有一种情况是磁盘头已经被其他系统写入了文件系统或分区信息导致ASM无法识别这是ASM盘状态会变成FOREIGN。新盘如果是旧设备重新利用的最好在操作系统层用dd把磁盘头清掉dd if/dev/zero of/dev/mapper/asm-data05 bs1M count100然后再重新扫描。4.3 rebalance误删盘后如何救回生产环境里手滑是难免的ADD盘的时候加错了盘或者DROP盘的时候名字写错都可能导致误操作。如果只是误把一块新盘DROP了rebalance尚未完成还有救。ASM提供了UNDROP命令ALTER DISKGROUP data UNDROP DISKS;这个命令可以恢复最后一次DROP操作中被移除的磁盘只要rebalance还没最终完成数据extent可能还没有完全清除就有机会恢复。但如果rebalance已经执行完毕UNDROP就无效了此时只能重新ADD磁盘。还有一种情况是ADD盘加错了路径把操作系统上正在使用的盘误加进了ASM磁盘组。这种操作风险很高ASM会尝试格式化该盘并写入ASM磁盘头如果盘上有正在使用的文件系统数据基本就废了。遇到这种情况第一时间要把错误磁盘从ASM中DROP掉并立即通知存储和系统团队评估数据恢复方案。这再次说明提前核实路径和磁盘头状态有多么重要。4.4 OCR和VOTE磁盘组的特殊处理ACFS、OCR和VOTE磁盘组也是ASM磁盘组很多人会想当然地用同样的ADD和DROP方式去迁移。但这里要特别提醒OCR和VOTE磁盘组承载的是Clusterware的核心文件路径一旦发生变化CRS可能起不来整个集群都会受影响。对于OCR磁盘组推荐使用ocrconfig工具来管理替换具体命令是ocrconfig -add 新磁盘组 ocrconfig -delete 旧磁盘组VOTE磁盘组则使用votedisk命令或crsctl命令进行操作crsctl replace votedisk 新磁盘组这类操作虽然底层也会触发ASM rebalance但流程完全不同建议由有经验的集群管理员来处理。文章前面讲到的ADD/DROP方式主要适用于普通数据磁盘组。5. 事后清理与复盘5.1 清理操作系统层旧盘配置迁移完成后旧盘虽然离开了磁盘组但操作系统层的配置还留着。如果不清理干净有两个隐患一是后续ASM扫描时可能把旧盘误识别为candidate盘二是容易让人搞混当前环境里到底有哪些盘在用。清理内容包括删除udev规则中对应的旧盘条目移除multipath配置中对应的磁盘映射从存储端解除LUN映射如果设备节点还残留在系统里用multipath -l确认没有活动路径后移除。做完这些之后再执行一次ASM磁盘扫描确认旧盘没有出现在candidate列表里。5.2 复盘文档与后续优化建议一次rebalance迁移做完我建议写一篇复盘文档核心记录三块内容迁移前后的磁盘组布局对比、rebalance各阶段的实际耗时和POWER配置、期间出现的异常和处理方式。这些数据对后续类似操作非常有参考价值。如果迁移后磁盘组空间充裕还可以考虑调整数据库的ASM相关参数比如DB_FILES、CONTROL_FILES等但这些属于可选项不影响正常业务。最后想分享一个经验就是迁移后不要马上把旧存储断掉至少保留一两天时间观察数据库运行状态确认所有文件访问都正常后再执行下线操作。我碰到过几次迁移当天一切正常但第二天有归档日志或备份任务触碰到旧盘路径才发现还有遗漏的依赖关系。这种问题在保留期内发现和处理都还来得及一旦旧存储彻底断电麻烦就大了。