Oracle 表空间又满了?我写了个脚本自动扩!
前言
最近这段时间又处理了几次 Oracle 表空间问题。
其实都不是什么复杂问题,收到告警以后登录数据库,查一下表空间使用率,再看看 datafile 还能不能继续 Autoextend;如果现有文件已经到 MAXSIZE,那就再加一个 datafile,整个操作可能几分钟都用不了。
但问题是,这种事情太多了。我现在手里维护的 Oracle 库不少:
- 今天这套 92%,进去看一下;
- 明天另外一套 96%,再进去看一下;
- 过几天某个 PDB 又快满了,还是同样的操作。
这种事情做一次没什么感觉,库多了以后,我就越来越不想干了。
既然每次判断逻辑都差不多,那为什么还要等告警出来,再让 DBA 登录数据库、查空间、切 PDB、加文件?所以这两天我把之前写过的一版表空间检查脚本重新翻了出来,干脆彻底改了一遍。
我的目标很简单:
以后业务表空间快满了,让它自己扩。
前前后后改了不少版,也拿几套实际环境反复跑了一遍。今天正好在一套生产 CDB 上真实触发了一次自动扩容,从判断到 ADD DATAFILE,再到扩容后的空间检查都符合预期,确保生产可以用了,那就拿出来分享一下。
完整脚本比较长,正文就不贴了。需要的直接到 ** 直接下载就行。

自动扩容不能只看 90%
这个脚本最核心的地方,其实不是 ADD DATAFILE,而是什么时候该扩,什么时候不该扩。
如果只写:表空间使用率 >= 90% 就自动扩容,脚本很容易误判。
比如一个 100GB 的表空间用了 91GB,只剩 9GB;另一个 2TB 的表空间虽然已经用了 96%,但可能还有几十甚至上百 GB 可用空间。两个都超过 90%,紧迫程度显然不一样。
另外,DBA_FREE_SPACE 查出来的 Free 也不能直接理解成“这个表空间还能用多少”。如果现有 datafile 开启了 Autoextend,并且距离 MAXSIZE 还有空间,这部分同样可以继续使用。
所以我建议大家把真正可用空间定义成 Available = Free + Growable,脚本也是这么设计的:
Free = 当前已经分配但尚未使用的空间
Growable = AUTOEXTENSIBLE=YES 的 datafile 距离 MAXSIZE 还能继续增长的空间
最终只有两个条件同时满足,脚本才会新增 datafile:
Used >= 90%
AND
Available < 30GB
也就是说,使用率已经进入高水位,而且真正能用的空间也不多了,才扩。 这个逻辑其实就是把平时 DBA 手工判断表空间是否需要扩容的过程交给脚本。

实际生产环境跑了一次
今天刚好在另外一套 Oracle 19c CDB 上碰到了一个很适合验证的场景。
当时几个业务表空间是这样的:
PDB TABLESPACE CURRENT_GB FREE_GB GROWABLE_GB AVAILABLE_GB
---- --------------------- ---------- -------- ------------ ------------
QMS QMSPROD_TABLESPACE 719.98 18.30 0.02 18.33
MES MESPROD_TABLESPACE 2749.87 31.73 0.13 31.86
SPC SPCPROD_TABLESPACE 959.97 39.21 0.03 39.24
MES 使用率已经到了 98.84%,但 Available 还有 31.86GB,SPC 使用率 95.92%,Available 还有 39.24GB,没有达到 <30GB 的条件,所以脚本没主动增加数据文件。
真正达到条件的是 QMS:
Used = 97.45%
Available = 18.33GB
97.45% >= 90% ✓
18.33GB < 30GB ✓
脚本自动识别以后,直接新增了一个 datafile:
[WARN] Threshold reached: QMS.QMSPROD_TABLESPACE
[WARN] QMS.QMSPROD_TABLESPACE:
ALLOCATED_MB=737256
USED_MB=718514
FREE_MB=18742
GROWABLE_MB=24
AVAILABLE_MB=18766
USED_PCT=97.45
[INFO] Datafile added successfully: QMS.QMSPROD_TABLESPACE
[INFO] Mode=OMF, SIZE=100M, NEXT=100M, MAXSIZE=30G
扩容前后再对比:
扩容前 扩容后
FILE_COUNT 24 25
FREE 18.30GB 35.10GB
GROWABLE 0.02GB 25.24GB
AVAILABLE 18.33GB 60.34GB
该扩的 QMS 扩了,MES 和 SPC 一个都没碰。这次真实跑完以后,这版脚本基本就达到了我想要的效果。
这个脚本能做什么?
我平时维护的 Oracle 环境本身就比较杂,什么版本的都有,还有 CDB,所以目前脚本适配了这些:
Oracle 11g / 19c
Non-CDB / CDB-PDB
OMF / Non-OMF
CDB 环境下会自动获取所有 READ WRITE PDB,不需要在脚本里提前写 PDB 名称,Non-CDB 则直接检查当前数据库。
每个业务表空间都会计算:
Used
Free
Growable
Available
达到阈值以后,根据当前环境自动选择 OMF 或 Non-OMF 的方式增加 datafile。
默认新增文件的属性:
- [x] SIZE 100M
- [x] AUTOEXTEND ON
- [x] NEXT 100M
- [x] MAXSIZE 30G
另外还保留了几个我觉得生产环境必须要有的东西:
- –check-only
- 防止脚本重复运行
- 完整运行日志
- SQLPlus 异常捕获
- 可选邮件通知
SYSTEM、SYSAUX、UNDO、TEMP 默认不会自动处理,脚本只负责业务永久表空间,至于 90% + 30GB 也不是写死的标准,可以根据自己的数据库规模和业务增长速度调整。
怎么部署?
拿到脚本以后,例如放到:
/home/oracle/jobs/tbs_auto_add_dbf.sh
先创建日志目录并增加执行权限:
mkdir -p /home/oracle/jobs/logs
chmod 750 /home/oracle/jobs/tbs_auto_add_dbf.sh
第一次部署后不要直接开启自动扩容,先检查 Shell 语法:
bash -n /home/oracle/jobs/tbs_auto_add_dbf.sh
然后执行:
bash /home/oracle/jobs/tbs_auto_add_dbf.sh --check-only
--check-only 会正常检查数据库版本、CDB/Non-CDB、PDB 和表空间,也会计算 Used、Free、Growable、Available,并判断哪些表空间已经达到扩容条件,但不会真正执行 ADD DATAFILE。
确认输出结果没有问题以后,再正式执行:
bash /home/oracle/jobs/tbs_auto_add_dbf.sh
最后在 Oracle 用户的 crontab 下设置定时任务,我设置的是每小时检查一次:
0 * * * * /bin/bash /home/oracle/jobs/tbs_auto_add_dbf.sh >> /home/oracle/jobs/logs/tbs_auto_add_dbf_cron.log 2>&1
部署完成后,正常情况下基本就不用管表空间的问题了:
- 没有达到阈值,脚本检查完直接结束;
- 达到阈值,自动新增 datafile;
- 如果执行失败,日志里也能看到具体原因。
最后
这个脚本本身没什么特别复杂的东西,但对 DBA 或者运维人员来说,这种自动化反而最实用。
因为真正长期消耗时间的,很多时候不是一年碰不到几次的大故障,而是这种每次几分钟、但一直在重复的事情。现在表空间这件事可以交给脚本以后,我就不准备再每天盯着 92%、95%、98% 一个个进去加文件了。
能自动处理的重复工作,就别再让 DBA 一遍遍手工做了。
- 点赞
- 收藏
- 关注作者
评论(0)