资讯动态

Oracle ASM空间分配与冗余机制全解析:AU、故障组与可用空间

发布时间:2026/10/14 4:32:15 来源:尧图企业网站定制
做 Oracle DBA 的只要碰过数据库文件管理基本都会遇到 ASM。ASM 全称 Automatic Storage Management它把裸设备或者操作系统里的磁盘统一接管组合成逻辑上的磁盘组Disk Group数据库文件不再需要手动放在文件系统里。说白了过去你要自己规划磁盘分区、做 RAID、玩 LVM用了 ASM这些工作大多可以省掉Oracle 自己负责把数据文件打散到各块磁盘上。可省事归省事ASM 背后的空间分配和冗余规则如果不理解深一点真正出问题的时候很容易抓瞎。我最早接触 ASM 还是 10g 时代后来一路用到 19c这些年遇到最多的问题就是两类一类是磁盘组剩几百GB空间但建数据文件竟然报 ORA-15041另一类是明明买了 2TB 磁盘做了 NORMAL 冗余结果可用空间只有 1TB连监控都显示 1TB总怀疑自己买错了容量。这两个问题背后全是分配机制和冗余规则在起作用。这篇文章就围绕Space Allocation和Redundancy展开把 AU、extent、条带化、故障组这几个核心概念讲透再结合实际操作说清楚怎么算可用空间、怎么监控、怎么扩容最后把我踩过的坑也一并放出来。适合看这篇内容的人大概是这几类刚接手 Oracle 环境、对 ASM 只停留在 create diskgroup 阶段的 DBA需要做磁盘组扩容或缩容、但不确定风险在哪里的运维以及被可用空间计算不对困扰、想从原理上搞明白的同学。如果你只是想跑个单机测试库看前几节就够用。1. 先把底层模型理顺AU、extent 和条带化1.1 AU 是怎么决定磁盘组最小刻度的ASM 分配空间不是按字节来的它有自己的最小单位叫 AUAllocation Unit默认是 1MB。也就是说任何文件在 ASM 里占空间都是按 1MB 的整数倍往上走的。这个设计很容易理解如果每次分配都精细到 KB 级别ASM 要管的块数量会爆炸检查磁盘均衡、维护镜像、做重平衡都会变得很慢如果 AU 太大比如 64MB文件系统里常见的碎片浪费又会被放大。1MB 是在管理开销和空间利用率之间比较平衡的默认值。创建磁盘组时可以通过 AU_SIZE 属性指定 AU 大小官方允许 1、2、4、8、16、32、64MB。但我要提醒一句除非你有非常明确的理由否则别动它。有人为了让大库少产生 extent 把 AU 改成 8MB结果后续恢复时恢复时间明显变长因为单块数据分布的粒度不一样了。AU 一旦在创建时定下来是没法直接改的只能重建磁盘组代价非常大。可以用生活里的例子帮助理解AU 就是仓库里的标准货架格子每个格子固定 1 平米。你放一件家具进去就算它只占 0.3 平米也还是占了一整个格子。数据库文件也一样最后一部分不足 1MB也照付 1MB 的空间。所以空间监控里看到的已使用和实际文件大小会有细微出入这很正常。1.2 extent 与文件在磁盘上的排布逻辑AU 是最小分配单位而真正在文件层起作用的是 extent。一个 extent 由若干个 AU 组成单个文件在底层被切成很多个 extent然后均匀地分散到磁盘组里的所有磁盘。这里的均匀不是嘴上说说ASM 在分配时是拿每块盘做轮询的一个磁盘组如果有几十块盘新写入的数据会尽量绕开最忙、最满的盘保证整体水位差不多。在 Oracle 12c 以前一个 extent 通常就是一个 AU。12c 以后引进了可变大小 extent在文件增长到一定程度后extent 会变大比如一次分配 64 个 AU。这样做的目的是减少文件元数据量因为大文件用大 extent需要记录的块更少ASM 管理起来更轻。但这些对我们日常使用的影响不大只要知道 allocation 是按格子 大块两层走就行。条带化也是分配的一部分。ASM 支持两种条带细粒度条带striping unit 128KB和粗粒度条带striping unit 1MB。日志文件、快速恢复区里的归档建议用细粒度条带因为这类文件以小块写为主条带太大反而不利数据文件用粗粒度就够了。创建表空间或指定文件位置时可以通过属性控制是否细粒度比如在 DB 端建表空间时指定 ASM 标签但一般默认都不用动。1.3 分配游标ASM 的公平分发器还有一个小机制值得知道就是 allocation cursor。ASM 在给文件分配 extent 时会为每块磁盘维护一个游标指示当前分配到了哪个 AU。每次分配它会往不同的磁盘上偏移防止所有新数据都压在同一块盘上。这个机制带来的结果是就算你往一个磁盘组里只写一个非常大的文件这个文件也会被拆到所有磁盘上不会出现单块盘写满、其他盘空闲的极端情况。理解这一点对排查空间问题很有帮助。一个常见的误解是磁盘组里有一块小盘空间是不是就先被小块占满其实不会ASM 会通过游标尽量均匀但如果某块盘容量明显比其他盘小它顶多影响整体的进度不会让数据全部堆到小盘上。反过来如果一块盘满了整个磁盘组的分配就会受阻因为 ASM 要保证分布均衡必须把数据写到剩余空间中相对最空闲的那块所有盘都满了才算是磁盘组满。2. 冗余级别对可用空间的影响比你想的大2.1 三种冗余级别先对号入座ASM 的 redundancy 分为三种EXTERNAL、NORMAL、HIGH。它决定了数据文件的内容在磁盘组里存几份也就是有没有镜像、镜像几路。EXTERNAL REDUNDANCY外部冗余。ASM 本身不做任何镜像数据只保留一份可用空间基本等于磁盘组总容量。它默认依赖底层——比如存储阵列已经做了 RAID或者你用的是测试环境、丢了也能重建。这种冗余模式不需要多个故障组最少一块盘也能建组是空间利用率最高的模式。NORMAL REDUNDANCY标准冗余也是最常见的选择。ASM 会给每个 extent 保存两份拷贝相当于镜像。两块拷贝会放到不同的故障组里这样任何一块物理盘坏了数据不会丢。代价就是可用空间大概只有总容量的一半。生产环境如果没有特殊需求我建议的默认选择就是 NORMAL性价比高。HIGH REDUNDANCY高冗余。每个 extent 保存三份拷贝。故障容忍度更强要求至少三个故障组可用空间只有总容量的三分之一左右。除非你是那种绝对不能停、存储底层又不可靠的系统否则生产环境其实不太会用 HIGH成本太高了。下面这个表值得收藏冗余级别镜像份数最少故障组数可用空间比例典型场景EXTERNAL无1约等于总容量阵列RAID保护、测试环境NORMAL2 份2约为总容量一半常规生产环境HIGH3 份3约为总容量三分之一高可用、低可靠存储2.2 故障组是什么为什么影响镜像落点故障组FAILGROUP是理解冗余空间绕不开的概念。一组磁盘如果共享同一个故障风险区比如同一块 HBA 卡、同一个电源域、同一台存储控制器的后端就应该归到同一个故障组。ASM 做镜像时有个硬性规则同一份数据的多个拷贝绝对不能放到同一个故障组里。道理很简单如果两块盘住在同一个故障域里一台控制器挂了镜像的两个拷贝同时失效镜像就白做了。创建 NORMAL 冗余磁盘组至少需要两个故障组HIGH 需要三个故障组。如果你创建时不指定 FAILGROUPASM 默认把每块盘单独当做一个故障组这样也能满足最低要求但物理上的同一故障域语义就丢了。生产环境最好显式规划故障组让 ASM 知道哪些盘可能同时出问题。我在实际项目中见过一个反面例子某现场把同一阵列同一控制器后端的两块盘建成了 NORMAL 冗余的两个默认故障组。ASM 以为两块盘是独立故障域实际上网卡、控制器都是共享的。后来控制器故障两块盘同时掉线磁盘组直接 force dismount数据不可用。这个案例提醒我故障组划分必须跟物理拓扑对齐否则冗余只是纸面上的。2.3 可用空间不是简单除以 2很多刚接触的人会拿总空间除以镜像份数来估算可用空间这个方向没大错但实际结果往往比估算略小。少掉的部分主要有两块第一是元数据。每个磁盘组都要预留一部分空间存放 ASM 自身的元数据比如磁盘目录、文件目录、分配位图等量级通常在几百 MB 到一两个 GB磁盘数越多、文件数越多元数据越占空间。第二是倾斜效应。同一个磁盘组里ASM 的分配均衡性要求镜像的拷贝分散到不同故障组而不同故障组里的盘容量不可能完全一样。如果故障组 A 总容量 2TB故障组 B 只有 1TB那么在做镜像时2TB 和 1TB 之间能配对的空间最多只有 1TB 的双倍多出来的 1TB 就没法被充分利用。ASM 会按所有故障组中容量最小的那个来折算有效容量这就叫倾斜。官方视图里已经把这些因素都算好了直接看 USABLE_FILE_MB 就是最可靠的。当你可以创建的文件空间大概等于所有磁盘可用空间经过冗余和倾斜折算后的值。别自己拿 TOTAL_MB 和 FREE_MB 简单除以 2那是数课不是工程。3. 空间分配实操建组、查空间、扩缩容3.1 创建磁盘组的完整姿势创建一个 NORMAL 冗余的磁盘组SQL 大概是这样的CREATE DISKGROUP data NORMAL REDUNDANCY FAILGROUP fg1 DISK /dev/oracleasm/disk1 NAME d1 FAILGROUP fg2 DISK /dev/oracleasm/disk2 NAME d2;如果你是外部冗余这样写CREATE DISKGROUP fra EXTERNAL REDUNDANCY DISK /dev/oracleasm/disk3 NAME d3;创建时需要注意几点磁盘组名称要见名知意DATA、FRA 这种比一堆随机字符强得多。DISK 路径必须指向 ASM 认到的磁盘不要自己猜路径先用 oracleasm listdisks 或者 asmcmd 确认。如果磁盘已经被其他磁盘组占用创建会失败。对于 NORMAL/HIGH指定 FAILGROUP 是强烈建议别偷懒。建完之后用 asmcmd lsdg 查看所有磁盘组的状态STATE 显示 MOUNTEDTYPE 显示 NORMAL/HIGH/EXTERNAL就能确认创建成功了。3.2 用对视图别总盯 FREE_MB空间监控最关键的一点是分清 FREE_MB 和 USABLE_FILE_MB。FREE_MB 是磁盘组里当前剩余物理空间不区分冗余USABLE_FILE_MB 是经过冗余系数、倾斜修正后还能真正拿来建文件的逻辑空间。NORMAL 冗余下如果 FREE_MB 显示还有 200GB那你能建的空间通常只有 100GB 左右HIGH 只有 60GB 左右。很多告警系统只看 FREE_MB结果警报要么提前触发要么滞后都是这个误区造成的。我个人习惯用这条 SQL 做日常巡检SELECT NAME, STATE, TYPE, TOTAL_MB, FREE_MB, USABLE_FILE_MB, ROUND((TOTAL_MB - FREE_MB) * 100 / TOTAL_MB, 1) AS used_pct FROM v$asm_diskgroup ORDER BY GROUP_NUMBER;重点关注 USABLE_FILE_MB 而不是 FREE_MB。如果 USABLE_FILE_MB 低于近期最大表空间增长需求就该考虑扩容了。asmcmd lsdg 的输出里同样有 Usable_FILE_MB 字段线上排查的时候用起来非常顺手。3.3 扩容、缩容与重平衡的时间账磁盘组加盘很简单一条命令ALTER DISKGROUP data ADD DISK /dev/oracleasm/disk4 NAME d4;加盘之后ASM 会自动对磁盘组做一次重平衡REBALANCE把现有数据重新分布到新盘上。整个过程不影响业务数据库文件继续可读可写。默认的重平衡速度比较保守可以通过 REBALANCE POWER 来控制1 到 11 可选11 最快但 I/O 压力最大。上线高峰期间我建议先别把 power 拉太高等业务低谷再说。如果加盘后发现重平衡走得太慢可以主动干预ALTER DISKGROUP data REBALANCE POWER 8;要查重平衡进度看 v$asm_operationSELECT GROUP_NUMBER, OPERATION, STATE, POWER, SOFAR, EST_WORK, EST_RATE FROM v$asm_operation;SOFAR 是已完成的工作量EST_WORK 是总工作量EST_RATE 是速率剩下的时间大致就是两者之差除以速率。我在一次给磁盘组加了两块 600GB 盘后用了默认 power跑了快四个小时才结束速度让我急得不行后来直接升到 6大概又多花了四十分钟就完成了。所以要不要调 power取决于你能不能接受重平衡期间的 I/O 干扰。缩容时一定要注意删除磁盘前空间必须足够承载被删除盘上的数据。否则 ASM 会报 ORA-15041告诉你空间不足。正确的操作是ALTER DISKGROUP data DROP DISK d4;ASM 会先执行重平衡把 d4 上的数据迁到其他盘然后才真正释放 d4。如果你只是因为盘即将故障想摘掉它可以先 DROP再物理拔盘但务必提前确认剩余空间够用并且要观察重平衡是否成功结束。4. 空间问题的真实案例与排查技巧4.1 ORA-15041 到底在说什么ORA-15041 是我见过最频繁的 ASM 空间错误字面意思是磁盘组空间不足无法完成空间分配。它的触发场景不只一种数据库新建数据文件时重平衡过程中源盘数据需要迁移到目标盘但目标盘空间不够DROP 磁盘时剩余空间不够承载被删盘数据临时文件、归档快速增长把 USABLE_FILE_MB 打满。排查步骤我一般是这样的第一先看 v$asm_diskgroup对比 FREE_MB 和 USABLE_FILE_MB确认剩余空间到底还有多少。第二看 v$asm_operation确认是否在重平衡中如果 EST_WORK 很大而 SOFAR 没动空间不足rebalance 会在后台反复重试。第三看故障组分布是不是某块盘空间满了导致整个分配受阻。第四检查最近是否有异常归档、超大临时文件在持续增长。如果是重平衡导致的空间不足处理办法很简单给磁盘组加盘或者删掉不必要的文件释放空间让重平衡继续。如果是新建数据文件失败那就只能扩容或者收缩现有数据文件。4.2 删了文件可用空间为什么没变化有段时间我收到告警说磁盘组使用率高清理了一批过期归档和备份文件后再看 FREE_MB 居然纹丝不动当时也懵了一下。后来冷静分析原因基本就是下面几种删除的是 DB 内部的归档日志而归档直接存储在文件系统或另一磁盘组里删了和当前磁盘组无关删除的表空间里还有段未回收比如回收站里的对象还占着空间虽然在 ASM 层删除了文件但 delete 操作瞬间 free 空间是即时的如果发现没变更可能是没删对地方磁盘组正在做 rebalance空间变化会被临时性掩盖。比较有效的方法是直接在 asmcmd 里确认asmcmd ls -s data看每个文件的大小和最后修改时间把真正占空间的大家伙找出来。ASM 的文件删除理论上会立即释放空间不需要手动 VACUUM 之类的操作释放不出来的时候优先检查是不是还有其他会话在占用文件、有没有挂在回收站里、是不是删到了别的路径上。4.3 重平衡像蜗牛爬多半是 power 没给够重平衡慢这个问题讨论频率也很高。默认情况下 ASM 重平衡的 power 是保守值尤其在 11g 以后的版本默认它会根据负载自动调整。碰上企业级大库数据量几十 TB重平衡根本不是按小时算是按天算的。处理原则很简单在大促或业务高峰不要动在低谷期可以把 power 调到 68 左右既提升速度又不至于让磁盘 I/O 饱和。如果你看到 v$asm_operation 里 SOFAR 一直在涨但 EST_WORK 也跟着涨那说明重平衡被新的分配推着走正常现象等等就行。如果 SOFAR 长时间不动查一下磁盘组内是否有 OFFLINE 的盘ASM 可能会暂停部分区的平衡。4.4 空间排查速查表遇到空间相关问题可以先对号入座现象可能原因处理动作磁盘组剩可空间但建文件报 ORA-15041USABLE_FILE_MB 不足 / rebalance 未完成 / 单盘瓶颈查 v$asm_diskgroup、v$asm_operation扩容或释放FREE_MB 和 USABLE_FILE_MB 差距明显冗余与倾斜的正常表现不是故障监控按 USABLE_FILE_MB 计算删除文件后空间未释放删的不是该磁盘组 / 回收站 / 文件被占用asmcmd ls -s 定位清理真正大文件重平衡迟迟不结束power 太低 / 数据量太大 / 磁盘 OFFLINE提升 power确认盘在线磁盘组整体使用率高但分布不均故障组容量差异大尽量均衡容量考虑加盘或迁移DROP 磁盘失败剩余空间不足以承载数据先加盘再重试 drop速查表是最后兜底的手段但真正解决问题的还是前面讲的空间分配逻辑ASM 的每一个分配决策都要兼顾冗余、故障组和均衡。所以做空间规划时永远要在物理空间之外留出逻辑空间的思维。4.5 几条压箱底的空间管理纪律最后说几条我自己一直遵守的经验放在这里算是给正文收尾。第一条磁盘组的空间使用率达到 85% 就应当启动扩容不要等到 90% 才动手。ASM 做扩容需要重平衡重平衡期间磁盘空间还会临时占用预留缓冲非常重要。第二条NORMAL 冗余不等于备份。ASM 镜像只防物理磁盘损坏不防误删、逻辑损坏、块坏。该做 RMAN 备份还得做。我有一次在生产环境恢复了误删的表空间数据靠的就是备份而不是依赖 ASM 镜像那真是救命的体会。第三条ASM 磁盘的命名和分组要规范。别用 oracleasm createdisk 乱建看着像 d1、d2 就行真正的磁盘组名、故障组名、文件路径都要统一规划否则几年后维护的人换成别人排查成本会翻倍。第四条对 AU_SIZE 的修改一定要克制。任何时候都不要因为看起来更有性能而乱调。ASM 默认设计在绝大多数场景下都是合理的。这个内容到这里就差不多了。我实际接触过的教训里最深刻的一次是某环境把 NORMAL 冗余的磁盘组配成三块容量差异很大的盘故障组也不均衡结果重平衡持续了一天半期间业务 I/O 明显受影响。从那次之后我做磁盘组容量规划一定会同时看每个故障组的最小盘容量而不是只看总容量。空间管理和冗余理解本质上是同一件事你越尊重 ASM 的物理规则它给你的可用空间就越可预期。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑