SYSAUX表空间使用率暴增处理方式

  • 问题版本:oracle 12.2.0.1及更高版本

最近给客户检查时发现客户的SYSAUX表空间随着业务量越增越多,排查确认是AUTO_STATS_ADVISOR_TASK客户环境中出现两种情况:一是手工执行exec prvt_advisor.delete_expired_tasks后,过期的统计信息顾问记录仍未被清除;二是本应自动清理的过期统计信息顾问记录未按时清除。经测试确认,该问题为 BUG 38326922(涉及版本≥19.27 且 < 25.1),需通过打补丁(Patch 38326922)或升级至 19.29 及以上版本修复。

若自查发现最旧的统计信息时间早于保留天数,且数据库版本在 19.26-19.28 左右,大概率是该 BUG 导致,建议尽早处理。

确认V$SYSAUX_OCCUPANTS中空间使用率占用最高的一项:

sql 复制代码
SET LINES 120   
COL OCCUPANT_NAME FORMAT A30   
SELECT OCCUPANT_NAME,SPACE_USAGE_KBYTES/1024/1024 AS SPACE_USAGE_GB FROM V$SYSAUX_OCCUPANTS ORDER BY SPACE_USAGE_KBYTES DESC;

查询DBA_SEGMENTS中SUSAUX表空间空间使用率最高的SEGMENT:

复制代码
 SELECT * FROM (SELECT SEGMENT_NAME,OWNER,TABLESPACE_NAME,BYTES/1024/1024 "SIZE(MB)",SEGMENT_TYPE FROM DBA_SEGMENTS WHERE TABLESPACE_NAME='SYSAUX' ORDER BY BYTES DESC) WHERE ROWNUM<=10;

确认使用率最大的为SM/ADVISOR与WRI$_ADV_OBJECTS时,可参考下方方法进行清理旧的Statistics Advisor

删除统计信息顾问任务(STATS_ADVISOR_ASK)

方法一:清空大量统计信息(AUTO_STATS_ADVISOR_TASK的数据全部清空,即使是bug版本也可以直接清理)

以sysdba身份执行以下命令:

复制代码
DECLARE 
v_tname VARCHAR2(32767); 
BEGIN 
v_tname := 'AUTO_STATS_ADVISOR_TASK'; 
DBMS_STATS.DROP_ADVISOR_TASK(v_tname); 
END;
/

注:情况后重新初始化才会有AUTO_STATS_ADVISOR_TASK的任务

复制代码
EXEC DBMS_STATS.INIT_PACKAGE();

方法二:手动清除过期的统计信息顾问记录

清除EXECUTION_DAYS_TO_EXPIRE的日期之前的AUTO_STATS_ADVISOR_TASK

sql 复制代码
exec prvt_advisor.delete_expired_tasks;

保留天数参考:

sql 复制代码
SELECT NAME,VALUE FROM wri$_adv_parameters WHERE task_id in (
SELECT ID FROM SYS.WRI$_ADV_TASKS WHERE NAME = 'AUTO_STATS_ADVISOR_TASK' and owner_name = 'SYS'
) AND NAME IN ('DAYS_TO_EXPIRE','EXECUTION_DAYS_TO_EXPIRE');

为避免delete数据量过大导致undo爆掉,可考虑下方的循环删除的方式:

清除30天前的统计信息,每次删除过期20天的任务

复制代码
set serveroutput on      
DECLARE      
    v_oldest INTEGER := 730;    -- 最老的数据为2年      
    v_increment INTEGER := 30;    -- 删除循环步长30天
    v_cur_age INTEGER;      
    v_min_age INTEGER := 30;     -- 保留一个月 ,该参数会影响EXECUTION_DAYS_TO_EXPIRE的结果    
BEGIN      
    v_cur_age := v_oldest;      
    WHILE v_cur_age >= v_min_age LOOP      
        dbms_sqltune.set_tuning_task_parameter(task_name => 'AUTO_STATS_ADVISOR_TASK', parameter => 'EXECUTION_DAYS_TO_EXPIRE', value => v_cur_age);      
        prvt_advisor.delete_expired_tasks;      
        v_cur_age := v_cur_age - v_increment;      
    END LOOP;      
EXCEPTION      
    WHEN OTHERS THEN      
        dbms_output.put_line('Execution halted with error number ' || sqlerrm);      
END;      
/

已执行的的统计信息时间参考SQL

sql 复制代码
select task_id, execution_name, execution_start, status
from dba_advisor_executions
where TASK_NAME='AUTO_STATS_ADVISOR_TASK'
order by execution_start desc;

https://support.oracle.com/support/?anchorId=\&documentId=KB122548\&page=sptemplate\&sptemplate=km-article

删除该任务后,重新组织表WRI$_ADV_ADTS及其索引

复制代码
SQL> ALTER TABLE WRI$_ADV_OBJECTS MOVE;   
SQL> ALTER INDEX WRI$_ADV_OBJECTS_IDX_01 REBUILD;   
SQL> ALTER INDEX WRI$_ADV_OBJECTS_PK REBUILD;  
SQL> ALTER INDEX WRI$_ADV_OBJECTS_IDX_02 REBUILD;
  • 重建后确认索引是可用的

    column index_name format a30
    select index_name,status from dba_indexes where table_name='WRI$_ADV_OBJECTS' and index_type like '%NORMAL';

  • 多租户环境,需按照以下方式进行重建:

    SQL> alter session set container=emrepdb;
    SQL> exec dbms_pdb.exec_as_oracle_script('ALTER TABLE WRI_ADV_OBJECTS MOVE'); SQL> exec dbms_pdb.exec_as_oracle_script('ALTER INDEX WRI_ADV_OBJECTS_PK REBUILD');
    SQL> exec dbms_pdb.exec_as_oracle_script('ALTER INDEX WRI_ADV_OBJECTS_IDX_01 REBUILD'); SQL> exec dbms_pdb.exec_as_oracle_script('ALTER INDEX WRI_ADV_OBJECTS_IDX_02 REBUILD');

测试执行参考命令

  • 手工执行AUTO_STATS_ADVISOR_TASK
sql 复制代码
DECLARE
  v_tname   VARCHAR2(128) := 'AUTO_STATS_ADVISOR_TASK';
BEGIN
  -- execute the task
  v_tname := DBMS_STATS.EXECUTE_ADVISOR_TASK(v_tname);
END;
/
  • 修改AUTO_STATS_ADVISOR_TASK的过期日期
sql 复制代码
EXEC DBMS_ADVISOR.SET_TASK_PARAMETER(task_name=> 'AUTO_STATS_ADVISOR_TASK', parameter=> 'EXECUTION_DAYS_TO_EXPIRE', value => 10);
  • 确认保留日期
sql 复制代码
select TASK_NAME,parameter_name, parameter_value FROM DBA_ADVISOR_PARAMETERS WHERE task_name='AUTO_STATS_ADVISOR_TASK' and PARAMETER_NAME='EXECUTION_DAYS_TO_EXPIRE'; 
  • 确认执行情况
sql 复制代码
select task_id, execution_name, execution_start, status
from dba_advisor_executions
where TASK_NAME='AUTO_STATS_ADVISOR_TASK'
order by execution_start desc;
相关推荐
翔云1234568 分钟前
RocksDB中,客户端每写入一次数据,需要访问几次磁盘
运维·数据库·mysql
DevOpenClub18 分钟前
职教高考控制线 API:招生类别枚举、筛选与空分数含义
java·数据库·高考
GeW2 小时前
新质生产力路线图解读:数据库性能优化与Linux调优专场
linux·数据库
在多学一点3 小时前
MYSQL第二次作业
android·数据库·mysql
Risehuxyc4 小时前
Microsoft.Data.Sqlite体验
数据库·sqlite
骑着蜗牛撵大象3274 小时前
MySQL 8.0 迁移后 SQL 变慢:执行计划里 3 类被忽略的成本差异
android·数据库·sql·mysql·优化器·执行计划
ZENERGY-众壹5 小时前
告警风暴怎么压?100MW 电站监控平台告警引擎架构复盘
数据库·架构·iot·电站监控
zhengfei6116 小时前
Go-fastdfs /reload 未授权访问: 有效PoC
数据库·sql
DevOpenClub6 小时前
高考教育信息问答 API:会话参数、资料引用与流式响应
java·数据库·高考
yuanyuan3346 小时前
2026枣庄带检测报告伸缩门品牌测评|本地服务
大数据·数据库·人工智能·伸缩门