ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Oracle 表空间监控与智能扩容实战:从“假使用率“到“存储感知扩容“

Oracle 表空间监控与智能扩容实战:从“假使用率“到“存储感知扩容“ 一篇写给一线 DBA 的实操笔记。不堆概念只讲清楚三件事使用率到底该怎么算、扩容该往哪里扩、ASM 满了该怎么办。一、先破除一个最常见的错觉几乎每个 Oracle 监控脚本的第一版都是这么写的SELECTa.tablespace_name,ROUND(a.total_size-NVL(b.free_size,0),2)ASused_mb,ROUND((a.total_size-NVL(b.free_size,0))/a.total_size*100,2)ASpctFROM(SELECTtablespace_name,SUM(bytes)/1024/1024total_sizeFROMdba_data_filesGROUPBYtablespace_name)a,(SELECTtablespace_name,SUM(bytes)/1024/1024free_sizeFROMdba_free_spaceGROUPBYtablespace_name)bWHEREa.tablespace_nameb.tablespace_name();它算的是**“已分配空间用了多少”而不是这个表空间还能长多大**。举个具体的例子。USERS表空间只有一个数据文件初始 100MB、AUTOEXTEND ON、MAXBYTES 32GB当前用了 90MB。按上面的 SQL90/100 90%值班电话立刻响。实际情况这个文件还能自动长到 32GB90/32768 ≈ 0.27%。一个报警一个其实很闲。误报多了人就会开始无视告警——这比漏报更危险。所以监控的第一步不是加阈值而是把分母换对。二、正确的容量模型上限不是一个数而是三个数的较小值很多人以为数据文件的上限就是MAXBYTES。其实它同时被三重约束卡住约束层说明① 数据文件自身DBA_DATA_FILES.MAXBYTESAUTOEXTEND ON时生效NO时上限就是当前BYTES② 引擎结构上限非 bigfilesmallfile数据文件最多2^22 - 1个块8K 块约 32GB32K 块约 128GB③ 底层存储文件系统或 ASM 磁盘组的可用空间——磁盘组只剩 5GB文件就长不到 32GB真正可扩展容量 min(①, ②, ③)。这也解释了为什么表空间使用率这个概念在多文件、跨存储时特别容易算错表空间的可扩展容量是它所有数据文件可扩展容量之和如果文件分散在不同文件系统或不同 ASM 磁盘组上必须分别按各自的存储上限算不能简单加总。一个够用的真实使用率查询SELECTdf.tablespace_name,ROUND(SUM(df.bytes)/1024/1024,2)ASallocated_mb,ROUND((SUM(df.bytes)-NVL(fs.free_bytes,0))/1024/1024,2)ASused_mb,ROUND(SUM(CASEWHENdf.autoextensibleYESTHENdf.maxbytesELSEdf.bytesEND)/1024/1024,2)ASmax_extendable_mb,ROUND((SUM(df.bytes)-NVL(fs.free_bytes,0))/SUM(CASEWHENdf.autoextensibleYESTHENdf.maxbytesELSEdf.bytesEND)*100,2)ASreal_pct_usedFROMdba_data_files df,(SELECTtablespace_name,SUM(bytes)free_bytesFROMdba_free_spaceGROUPBYtablespace_name)fsWHEREdf.tablespace_namefs.tablespace_name()GROUPBYdf.tablespace_name,fs.free_bytesORDERBYreal_pct_usedDESC;MAXBYTES的默认值陷阱建库时若只写AUTOEXTEND ON而不写MAXSIZE默认上限是块大小 × 2^22 - 18K 块约 32GB。所以看到MAXBYTES是一个奇怪的接近 32GB 的值别惊讶那是默认值。关于DBA_TABLESPACE_USAGE_METRICS方便但别全信Oracle 自带的DBA_TABLESPACE_USAGE_METRICS用起来很省事但它本质是MMON 进程产出的缓存指标有延迟、非实时。更麻烦的是它有几个已知坑数据文件数达到db_files上限时底层GV$FILESPACE_USAGE返回空该视图跟着返回空——监控脚本会看不到任何表空间非常隐蔽对应 Doc ID 1903251.1。12c 早期版本对 UNDO 表空间的使用率报告不准确视图定义没有随 CDB 架构调整且 11→12 之间GV$FILESPACE_USAGE的FLAG列标识方式变了原有的 UNDO 识别逻辑失效。结论用它做全库初筛可以做精确判断和高风险表空间细化时直接查DBA_DATA_FILESDBA_FREE_SPACE自己算。三、临时表空间和 UNDO不能套用普通表空间的逻辑这是另一个高频误区。三类表空间的满含义完全不同1临时表空间使用率接近 100%通常是正常的Oracle 7.3 以后临时表空间使用率长期贴近 100% 是常态不能仅凭这个数字判断系统异常。真要看临时段占用用V$SORT_USAGE/V$TEMPSEG_USAGE去定位是哪个会话、哪种段类型排序、Hash Join、临时表、LOB在占。⚠️不要用V$TEMP_SPACE_HEADER/GV$TEMP_SPACE_HEADER算临时表空间使用率——它反映的是历史峰值的初始化块数不是当前实际分配会得出错误结果。2UNDO 看的是 OOS不是简单百分比UNDO 表空间不足最直接的信号在 AWR 的 UNDO 统计里——OOSOut Of Space计数不为零就说明 UNDO 空间不足。配合V$UNDOSTAT观察 undo 段分配与偷窃情况比单纯看使用率靠谱得多。3MAXBYTES 0的含义在DBA_DATA_FILES里MAXBYTES 0表示该文件没有设置扩展上限而不是不能扩展别把它当成 0 容量去算。四、智能扩容的关键先判断往哪里扩表空间满了要扩容但扩到错误的地方后果比不扩还严重。最典型的事故RAC 环境下有人看到表空间 90%不看数据文件路径直接ADD DATAFILE结果文件落到了某个节点的本地$ORACLE_HOME或本地目录。接下来就是跨实例访问失败、重启后节点起不来、还要做数据文件搬迁……一个顺手扩容变成一场故障。同类问题在单机上也存在文件被加到默认 HOME、加到莫名路径后续管理一团乱。所以自动扩容脚本里第一件事不是ALTER TABLESPACE而是识别存储类型。判断方法很简单——ASM 数据文件名以开头DATA/ORCL/DATAFILE/users.xxx.dbf→ ASM磁盘组名取第一个/前的部分/oradata/orcl/users01.dbf→ 文件系统取dirname作为目录两者后续处理完全不同存储类型剩余空间怎么取怎么加数据文件文件系统df -Pm 目录取第 4 列拼出完整路径 文件名ASM查v$asm_diskgroup的usable_file_mb只给磁盘组文件名由 ASM 自动生成一个存储感知的扩容判断流程表空间真实使用率 90% │ ├─ 取该表空间任一数据文件路径 │ ├─ 以 开头? ── 是 ─→ ASM查 usable_file_mb │ └─ 否 ─→ FSdf -Pm 目录 │ ├─ 剩余空间 安全水位? ── 是 ─→ 只告警不扩容避免撑爆存储 │ └─ 否 ─→ ADD DATAFILEASM 只给磁盘组FS 拼路径时间戳命名 │ └─ 输出含 ORA-? ─→ 失败告警否则成功通知核心脚本骨架#!/bin/bash## oracle_tablespace_guard.sh# 表空间真实使用率检测 存储感知的智能扩容 告警# 适用: Oracle 11g / 12c / 19c / 21c / 23ai# 注意: 仅供参考生产使用前请充分测试#exportORACLE_HOME/u01/app/oracle/product/19.0.0/dbhome_1exportORACLE_SIDORCLexportPATH$ORACLE_HOME/bin:$PATHDB_USER/ as sysdbaALERT_THRESHOLD80# 仅告警AUTOADD_THRESHOLD90# 自动扩容ADD_SIZE_MB2048# 每次新增大小ADD_MAX_MB32768# 新文件扩展上限ADD_NEXT_MB256# 扩展步长SAFE_FREE_MB5120# 存储安全水位低于则只告警LOGDIR/home/oracle/scripts/logLOGFILE$LOGDIR/ts_guard_$(date%Y%m%d).logDINGTALK_URL# 钉钉机器人 WebhookMAIL_TO# 告警邮箱mkdir-p$LOGDIRlog(){echo[$(date%F %T)]$1|tee-a$LOGFILE;}notify(){[-n$DINGTALK_URL]curl-s-HContent-Type: application/json\-d{\msgtype\:\text\,\text\:{\content\:\$1\}}$DINGTALK_URL/dev/null;}log 表空间巡检开始 # 1) 采集真实使用率表空间|已分配|已用|可扩展上限|真实使用率TS_LIST$($ORACLE_HOME/bin/sqlplus-S$DB_USEREOFSET PAGESIZE0FEEDBACK OFF HEADING OFF LINESIZE400TRIMSPOOL ON SELECT df.tablespace_name|||||ROUND(SUM(df.bytes)/1024/1024,2)|||||ROUND((SUM(df.bytes)-NVL(fs.free_bytes,0))/1024/1024,2)|||||ROUND(SUM(CASE WHENdf.autoextensibleYESTHEN df.maxbytes ELSE df.bytes END)/1024/1024,2)|||||ROUND((SUM(df.bytes)-NVL(fs.free_bytes,0))/ SUM(CASE WHENdf.autoextensibleYESTHEN df.maxbytes ELSE df.bytes END)*100,2)FROM dba_data_files df,(SELECT tablespace_name, SUM(bytes)free_bytes FROM dba_free_space GROUP BY tablespace_name)fs WHERE df.tablespace_namefs.tablespace_name()GROUP BY df.tablespace_name, fs.free_bytes ORDER BY5DESC;EXIT EOF)[-z$TS_LIST]{logERROR: 采集失败请检查数据库连接;notify【Oracle】$ORACLE_SID表空间巡检失败连接异常;exit1;}echo$TS_LIST|whileIFS|read-rTS ALLOC USED MAXMB PCT;do[-z$TS]continuelog表空间[$TS] 已分配${ALLOC}MB 已用${USED}MB 上限${MAXMB}MB 真实使用率${PCT}%PCT_INT${PCT%.*}if[${PCT_INT:-0}-ge$AUTOADD_THRESHOLD];then# 2) 取存储位置LOC$($ORACLE_HOME/bin/sqlplus-S$DB_USEREOF SET PAGESIZE 0 FEEDBACK OFF HEADING OFF LINESIZE 400 TRIMSPOOL ON SELECT file_name FROM dba_data_files WHERE tablespace_name$TS AND ROWNUM1; EXIT EOF)LOC$(echo$LOC|head-1|tr-d )ifecho$LOC|grep-q^;then# ---- ASM ----DG$(echo$LOC|cut-d/-f1|tr-d)FREE$($ORACLE_HOME/bin/sqlplus-S$DB_USEREOF SET PAGESIZE0FEEDBACK OFF HEADING OFF LINESIZE200TRIMSPOOL ON SELECT NVL(MIN(usable_file_mb),0)FROM v\$asm_diskgroupWHEREname$DG;EXIT EOF)FREE$(echo$FREE|head-1|tr-d )CLAUSE$DG SIZE${ADD_SIZE_MB}M AUTOEXTEND ON NEXT${ADD_NEXT_MB}M MAXSIZE${ADD_MAX_MB}MTARGET$DGelse# ---- 文件系统 ----DIR$(dirname$LOC)FREE$(df-Pm$DIR|awkNR2{print $4})NEWFILE${DIR}/${TS,,}_$(date%Y%m%d%H%M%S).dbfCLAUSE$NEWFILE SIZE${ADD_SIZE_MB}M AUTOEXTEND ON NEXT${ADD_NEXT_MB}M MAXSIZE${ADD_MAX_MB}MTARGET$DIRfiif[${FREE:-0}-lt$SAFE_FREE_MB];thenlogWARN: [$TS] 所在存储$TARGET剩余${FREE}MB 安全水位${SAFE_FREE_MB}MB跳过自动扩容notify【Oracle告警】$ORACLE_SID[$TS] 使用率${PCT}%但$TARGET仅剩${FREE}MB需人工介入continuefilog执行: ALTER TABLESPACE$TSADD DATAFILE$CLAUSERES$($ORACLE_HOME/bin/sqlplus-S$DB_USEREOF SET PAGESIZE 0 FEEDBACK OFF HEADING OFF LINESIZE 400 ALTER TABLESPACE$TSADD DATAFILE$CLAUSE; EXIT EOF)ifecho$RES|grep-qiORA-;thenlogERROR: [$TS] 扩容失败:$RESnotify【Oracle告警】$ORACLE_SID[$TS] 自动扩容失败$RESelselogOK: [$TS] 扩容成功${ADD_SIZE_MB}MBnotify【Oracle通知】$ORACLE_SID[$TS] 使用率${PCT}%已自动扩容${ADD_SIZE_MB}MBfielif[${PCT_INT:-0}-ge$ALERT_THRESHOLD];thenlogWARN: [$TS] 使用率${PCT}% 超过告警阈值${ALERT_THRESHOLD}%notify【Oracle告警】$ORACLE_SID[$TS] 真实使用率${PCT}%请关注fidonelog 表空间巡检结束 脚本中ORACLE_HOME、ORACLE_SID、Webhook、邮箱均为占位值生产使用前请按实际环境替换并在测试环境验证。几个设计取舍说明用usable_file_mb而不是free_mb判断 ASM 能否扩容下一节详述。存储低于安全水位就只告警、不动手——把存储撑爆比表空间满更难收拾。文件系统新文件名带时间戳天然避免重名冲突ASM 则由 ASM 自动命名。失败必须告警不能让ORA-被静默吞掉。五、ASM 磁盘组表空间满了要扩磁盘组满了更棘手5.1 容量查询free_mb和usable_file_mb不是一回事SELECTname,ROUND(total_mb/1024,2)AStotal_gb,ROUND(free_mb/1024,2)ASfree_gb,ROUND((total_mb-free_mb)/total_mb*100,2)ASused_pct,ROUND(usable_file_mb/1024,2)ASusable_file_gbFROMv$asm_diskgroupORDERBYused_pctDESC;free_mb物理剩余。usable_file_mb考虑冗余度normal/high后真正能放文件的可用空间。做扩容判断时看usable_file_mb。normal 冗余下free_mb看着挺多usable_file_mb可能只有一半。这两个数搞混是以为能扩、结果扩不动的常见原因。两个已知的坑从数据库实例查v$asm_diskgroup某些老版本10gR1free_mb返回 0这是为减少实例间消息传递的设计行为10gR2 起改变。稳妥做法是连ASM 实例查或用asmcmd lsdg。未挂载磁盘组的TOTAL_MB可能显示异常把未挂载磁盘组的总和算了进来内部 Bug。做容量统计前先确认磁盘组状态是MOUNTED。5.2 asmcmd日常运维的好帮手asmcmd lsdg# 各磁盘组容量/状态asmcmdls-lDATA# 磁盘组内文件asmcmdduDATA# 目录占用统计asmcmd lsop# 12c 查看 rebalance 等操作进度asmcmd--instASM2# 12c 从任意节点连指定 ASM 实例5.3 rebalance加盘减盘后别急着走人-- 监控进度SELECTgroup_number,operation,state,power,est_minutesFROMv$asm_operation;-- 调整力度越大越快对业务 I/O 冲击越大ALTERDISKGROUPDATAREBALANCE POWER5;生产建议在业务低峰期做边做边看v$asm_operation。大磁盘组几十上百块盘在极端情况下会遇到 partner slot 达到结构上限、rebalance 起不来的问题需要 offline/online 相关磁盘绕过——这属于较深的坑遇到时不要盲目drop force。5.4 磁盘组快满时的应急动作当 ASM 磁盘组空间严重不足时第一步是先关掉数据文件的自动扩展防止文件自动增长把最后的空间也吃光-- 单个文件ALTERDATABASEDATAFILEDATA/ORCL/DATAFILE/users.xxx.dbfAUTOEXTENDOFF;可以先用DBA_DATA_FILES查出所有AUTOEXTENSIBLEYES的文件批量生成autoextend off语句先把局面稳住再规划扩容或加盘。六、从 11g 到 23ai/26ai和监控/扩容相关的几个变化ASMCMD 能力持续增强12c 起新增lsop直接看 rebalance 进度、--inst跨节点连 ASM 实例、pwmove在线移动密码文件等多节点 ASM 管理方便很多。RAC 路径约束始终存在无论哪个版本RAC 下数据文件必须在共享存储。dbca静默建库时若漏了-datafileDestination DATA -storageType ASM -diskGroupName DATA数据文件和 spfile 会落到本地文件系统直接导致远程节点启动失败。bigfile vs smallfile 的上限差异要记住2^22-1块的结构上限针对 smallfilebigfile 单文件可远大于此这也是大库常选 bigfile 的原因之一。监控视图本身的版本差异如前面提到的DBA_TABLESPACE_USAGE_METRICS在 CDB/UNDO 场景的偏差跨版本迁移监控脚本时要重新验证。七、收尾自动化的边界最后强调几点也是整篇文章最想传递的先把分母算对再谈阈值。基于已分配空间的使用率是假指标会制造大量误报让人对告警麻木。容量上限是三层约束的较小值文件MAXBYTES、引擎结构上限、底层存储剩余。跨存储时逐文件算别加总。自动扩容前必须识别存储类型。RAC 下把数据文件加到本地路径是比表空间满更严重的事故。ASM 看usable_file_mb文件系统看df两者不可混用。监控与扩容可以拆开。保守团队只用监控、扩容留人工确认本身就是一种合理的风控。先测试再生产。阈值、路径、命名规则都要按环境替换验证。把这几件事做对凌晨三点的电话会少很多。
返回列表