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;
相关推荐
邵伯8 小时前
为什么你的 SELECT 有时会阻塞?
数据库·后端
洛小豆8 小时前
代码修仙录 · 第1期:宗门大阵崩了?只因少了毫秒三魂!
数据库·后端·mysql
2501_941886868 小时前
基于法兰克福金融系统实践的高可靠消息队列设计与多语言实现经验总结分享
服务器·前端·数据库
ANnianStriver8 小时前
redis安装包方式下载安装
数据库·redis·缓存
云和恩墨9 小时前
表空间、巡检、建库:DBA最熟悉的3个场景,正在被zCloud开放运维中心重新定义
运维·数据库·表空间·dba·巡检·建库
Austindatabases9 小时前
临时工说:上云后给 我一个 不裁 DBA的理由
数据库·dba
IT邦德9 小时前
为什么顶尖DBA,都爱混社交圈?
数据库·dba
tqs_123459 小时前
事务消息实现
数据库·java-rocketmq
言之。9 小时前
DDIA第四章 数据库存储引擎与索引技术深度解析
数据库·ddia
山沐与山9 小时前
【Redis】读写锁实战详解:读多写少场景的性能优化利器
数据库·redis·性能优化