一、表空间管家
以下是一个针对生产环境设计的Oracle ASM磁盘空间监控及自动添加数据文件的脚本方案,结合了ASM空间监控、表空间扩展逻辑及生产环境安全规范,适用于Oracle 11g/12c/19c等版本。
通过crontab设置每小时执行一次,避免频繁检查:
0 */1 * * * /opt/scripts/asm_auto_add_datafile.sh
# 脚本名称: asm_auto_add_datafile.sh
# 功能: 监控ASM磁盘组空间并自动扩展表空间数据文件
# 适用环境: Oracle 11g/12c/19c, Linux/Unix
# 配置参数
ORACLE_SID=orcl
THRESHOLD_PCT=10 # ASM磁盘组剩余空间告警阈值(%)
DATAFILE_SIZE=20G # 新增数据文件大小
LOG_FILE=/var/log/oracle/asm_auto_add.log
# 获取ASM磁盘组空间信息
get_asm_diskgroup_info() {
sqlplus -S / as sysdba <<EOF
SET FEEDBACK OFF HEADING OFF LINESIZE 200
SELECT name||'|'||ROUND((free_mb/total_mb)*100,2)
FROM v\$asm_diskgroup
WHERE ROUND((free_mb/total_mb)*100,2) < $THRESHOLD_PCT;
EXIT;
EOF
}
# 获取需要扩展的表空间列表
get_tablespace_list() {
local dg_name=$1
sqlplus -S / as sysdba <<EOF
SET FEEDBACK OFF HEADING OFF LINESIZE 200
SELECT a.tablespace_name
FROM (
SELECT tablespace_name, SUM(bytes)/1024/1024/1024 used_gb
FROM dba_segments
GROUP BY tablespace_name
) a, dba_tablespaces b
WHERE a.tablespace_name = b.tablespace_name
AND b.contents = 'PERMANENT'
AND a.used_gb / (SELECT SUM(bytes)/1024/1024/1024
FROM dba_data_files
WHERE tablespace_name = a.tablespace_name) > 0.9
AND EXISTS (
SELECT 1
FROM dba_data_files
WHERE tablespace_name = a.tablespace_name
AND file_name LIKE '+${dg_name}%'
) AND ROWNUM <= 2; # 限制单次处理表空间数量
EXIT;
EOF
}
# 主逻辑
main() {
echo"$(date '+%Y-%m-%d %H:%M:%S') - 开始执行ASM空间监控..." >> $LOG_FILE
# 遍历空间不足的ASM磁盘组
get_asm_diskgroup_info | while IFS='|'read dg_name free_pct; do
echo"$(date) - 检测到磁盘组 ${dg_name} 剩余空间不足: ${free_pct}%" >> $LOG_FILE
# 获取需扩展的表空间
get_tablespace_list "$dg_name" | whileread ts_name; do
datafile_path="+${dg_name}"
# 执行数据文件添加
sqlplus -S / as sysdba <<EOF >> $LOG_FILE 2>&1
WHENEVER SQLERROR EXIT SQL.SQLCODE
ALTER TABLESPACE ${ts_name} ADD DATAFILE '${datafile_path}'
SIZE ${DATAFILE_SIZE} AUTOEXTEND ON NEXT 1G MAXSIZE 32G;
EXIT;
EOF
# 错误处理
if [ $? -eq 0 ]; then
echo"$(date) - 成功添加数据文件: ${datafile_path} 到表空间 ${ts_name}" >> $LOG_FILE
else
echo"$(date) - 错误: 添加数据文件到 ${ts_name} 失败! 检查ORA错误码." >> $LOG_FILE
fi
done
done
echo"$(date) - 监控执行完成." >> $LOG_FILE
}
# 执行主函数
main
二、自动生成AWR报告
每天生成关键数据库的AWR报告,自动分析TOP SQL和性能瓶颈,提前发现慢查询,避免业务高峰期的性能雪崩,脚本具体跳转链接查看。
三、自动删除分区
相信很多小伙伴因为删除数据而烦恼,有其一些历史数据长时间存在数据库,存储空间岌岌可危,那么下面这个定时删除,一定会给你带来帮助,其实就是一个存储过程,挂一个定时任务就行。
--存储过程脚本
GRANT SELECT ON dba_tab_partitions TO SYSTEM;
CREATE OR REPLACE FUNCTION high_value_to_date(
p_table_name VARCHAR2,
p_partition_name VARCHAR2
) RETURN DATE IS
v_high_value LONG;
v_date DATE;
BEGIN
SELECT high_value
INTO v_high_value
FROM dba_tab_partitions
WHERE table_name = p_table_name
AND partition_name = p_partition_name;
EXECUTE IMMEDIATE 'BEGIN :1 := ' || v_high_value || '; END;'
USING OUT v_date;
RETURN v_date;
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END;
exec DROP_OLD_PARTITIONS('SYSTEM');
SELECT * FROM DBA_ERRORS WHERE name='PURGE_OLD_PARTITIONS'
CREATE OR REPLACE PROCEDURE drop_old_partitions(p_owner IN VARCHAR2) IS
v_cutoff_date DATE;
v_partition_high_value DATE;
v_sql VARCHAR2(4000);
BEGIN
-- 计算截止日期(保留数据的起始时间点)
v_cutoff_date := TRUNC(SYSDATE) - 1;
-- 遍历目标表所有分区
FOR part_rec IN (
SELECT
table_owner,
table_name,
partition_name,
high_value
FROM
dba_tab_partitions
WHERE
TABLE_OWNER= upper(p_owner)
AND interval = 'YES'
AND high_value IS NOT NULL
) LOOP
BEGIN
-- 动态执行HIGH_VALUE转换
EXECUTE IMMEDIATE 'BEGIN :1 := ' || part_rec.high_value || '; END;'
USING OUT v_partition_high_value;
DBMS_OUTPUT.PUT_LINE('Partition: ' || part_rec.partition_name
|| ', High Value: ' || TO_CHAR(v_partition_high_value, 'YYYY-MM-DD'));
-- 检查分区是否需要删除
IF v_partition_high_value < v_cutoff_date THEN
v_sql := 'ALTER TABLE ' || part_rec.table_owner || '.' || part_rec.table_name
|| ' DROP PARTITION ' || part_rec.partition_name;
DBMS_OUTPUT.PUT_LINE('Executing: ' || v_sql);
EXECUTE IMMEDIATE v_sql;
DBMS_OUTPUT.PUT_LINE('Successfully dropped partition: ' || part_rec.partition_name);
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error processing partition ' || part_rec.table_owner || '.' || part_rec.table_name
|| ': ' || SQLERRM);
END;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Partition cleanup completed.');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Critical error: ' || SQLERRM);
RAISE;
END drop_old_partitions;
/
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'auto_drop_old_partitions',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN drop_old_partitions(''SYSTEM''); END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY; BYHOUR=2;',
enabled => TRUE,
comments => 'Automatically drop old interval partitions'
);
END;
/
-- 查询所有定时任务(当前用户)
SELECT job_name, enabled, state, last_start_date, next_run_date, repeat_interval
FROM dba_scheduler_jobs WHERE JOB_NAME='AUTO_DROP_OLD_PARTITIONS'
-- 查询指定任务详情
SELECT * FROM dba_scheduler_jobs WHERE job_name = 'AUTO_DROP_OLD_PARTITIONS';
-- 查看任务失败详情
SELECT job_name, actual_start_date, run_duration, error#, additional_info
FROM dba_scheduler_job_run_details
WHERE job_name = 'AUTO_DROP_OLD_PARTITIONS'
AND status = 'FAILED';
四、总结
自动化不是取代DBA,而是将精力从重复劳动转移到架构优化,立即部署这些脚本,告别996!
如果字段的最大可能长度超过255字节,那么长度值可能…
只能说作者太用心了,优秀
感谢详解
一般干个7-8年(即30岁左右),能做到年入40w-50w;有…
230721