由于管理的库最近发生了表空间不够的问题,原本是做了每小时任务,低于30G就邮件报警的功能,但是那天由于一位同事临时导入大量数据,导致第二天空间不够。
为了防止这种问题的继续发生,做了表空间自动添加功能:
说明:
首先做逻辑判断,如果当前的表空间小于配置的大小 如: 40G( 表空间的剩余和自动扩展文件的总大小),
首先创建如下视图:
create or replace view dba_tablespace_free as select a.tablespace_name,a.total_space_mb allocated_space_mb,round(b.free_space_mb,2) free_space_mb,(a.max_space-a.total_space_mb) free_allocate_mb,round(a.max_space,2) max_space_mb, round((a.total_space_mb-b.free_space_mb)/a.total_space_mb*100,2) pct_usage,round(a.total_space_mb/a.max_space*100,2) pct_allocated from (select tablespace_name,sum(bytes)/1024/1024 total_space_Mb,decode(sum(maxbytes/1024/1024),0, sum(bytes)/1024/1024,sum(case when AUTOEXTENSIBLE='YES' then maxbytes else bytes end)/1024/1024) max_space from dba_data_files group by tablespace_name)a,(select tablespace_name, sum((bytes)/1024/1024) free_space_Mb from dba_free_space group by tablespace_name) b where a.tablespace_name=b.tablespace_name;
然后创建监控存储过程:
create or replace procedure p_monit_tbs_ceshi as --created by huangchao,2011-09-13 --监控表空间 vMessage varchar(250); vDb_name varchar2(10); --数据库名 vTBS_FREE_GB number; --剩余表空间阀值 monitor_date DATE := trunc(sysdate-2); v_name varchar2(200); cn integer; lv_errinfo varchar2(200); v_sql varchar2(1000); BEGIN --获取数据库名 vTBS_FREE_GB :=40; select name into vDb_name from v$database; for x in (SELECT tablespace_name,(free_space_mb+free_allocate_mb)total_free_mb FROM dba_tablespace_free WHERE tablespace_name NOT IN ('TEST1_DATA') loop if (round(x.total_free_mb/1024,2)<= vTBS_FREE_GB) then begin vMessage := '[报警] 数据库' || vDb_name || '表空间'|| x.tablespace_name||'还剩'||x.total_free_mb|| 'MB'; --判断磁盘组是否大于200G select count(1) into cn from V$asm_Diskgroup where free_mb/1024 >200; if cn =0 then for x in (select mail from Moni_Alert_Mail where flag = 1) loop sendmail(Subject =>'新库每个磁盘组文件不足200G' ,v_Msg => '新库每个磁盘组文件不足200G',Receipint => x.mail); end loop; else if cn>=1 then select name into v_name from (select * from V$asm_Diskgroup where free_mb/1024 >200 order by free_mb desc) where rownum =1; v_sql := 'alter tablespace '||x.tablespace_name||' add datafile ''+'||v_name||''' size 256M autoextend on next 100M'; begin execute immediate v_sql; for x in (select mail from Moni_Alert_Mail where flag = 1) loop sendmail(Subject =>'表空间不足,自动添加数据文件成功' ,v_Msg => vmessage||chr(10)||v_sql,Receipint => x.mail); end loop; EXCEPTION when others THEN lv_errinfo := SQLERRM; for x in (select mail from Moni_Alert_Mail where flag = 1) loop sendmail(Subject =>'警告,自动添加数据文件失败' ,v_Msg => vmessage||chr(10)||v_sql,Receipint => x.mail); end loop; end; end if; end if; end; end if; end loop; COMMIT; end;
该存储过程每隔1小时执行一次。