ORA-1628: max # extents 32765 reached for rollback segment 错误处理

客户执行过程,其中有长查询(把结果插入到表中,insert into tab1 select * from view_1之类的语句)报错经查看告警日志,告警日志中出现如下错误内容:

Mon Sep 29 12:06:05 2014
ORA-1628: max # extents 32765 reached for rollback segment _SYSSMU465_3766520548$
Mon Sep 29 12:29:45 2014
minact-scn: useg scan erroring out with error e:12751
Mon Sep 29 12:33:45 2014
ORA-1628: max # extents 32765 reached for rollback segment _SYSSMU236_3356150501$
Mon Sep 29 12:34:55 2014
SMON: Parallel transaction recovery tried

错误是rollback segment 的extents 已经达到了32765已经不能再通过增加extents来扩展段大小了,就是上面段_SYSSMU465_3766520548$和段_SYSSMU236_3356150501$的碎片过多。
查看相关数据库信息
1)查看undo管理
SQL> show parameter undo

NAME                      TYPE              VALUE
--------------------    -----------  ------------------
undo_management    string     AUTO
undo_retention         integer    7110
undo_tablespace       string     UNDOTBS11

2)查看undo表空间
SQL> select distinct status,tablespace_name ,to_char(round(sum(bytes)/1024/1024)) sizeM,count(1) from dba_undo_extents group by status,tablespace_name;

STATUS     TABLESPACE_NAME   SIZEM    COUNT(1)
---------  ---------------  -------    --------- 
EXPIRED      UNDOTBS12    55643     17001
UNEXPIRED    UNDOTBS11    893       415
UNEXPIRED    UNDOTBS12    1473     287
EXPIRED      UNDOTBS11    43777     69141
3)查看报错的两个回滚段
SQL> select sum(blocks), count(*), SEGMENT_NAME
  from sys.dba_extents t
 WHERE T.segment_name IN
       ('_SYSSMU465_3766520548$', '_SYSSMU236_3356150501$')
 GROUP BY T.segment_name;
 
SUM(BLOCKS) COUNT(*)      SEGMENT_NAME
----------- ----------    -----------------------
    1528552 32765        _SYSSMU465_3766520548$
     753016 32765        _SYSSMU236_3356150501$


SQL> SELECT T.segment_name,T.BLOCKS,T.EXTENTS FROM DBA_SEGMENTS T WHERE T.segment_name IN ('_SYSSMU465_3766520548$', '_SYSSMU236_3356150501$');


SEGMENT_NAME          BLOCKS    EXTENTS
-------------          ---------    ----------  
_SYSSMU236_3356150501$ 753016      32765
_SYSSMU465_3766520548$ 1528552      32765
SQL> SELECT T.segment_name,T.BLOCKS,T.EXTENTS FROM DBA_SEGMENTS T WHERE T.segment_name IN ('_SYSSMU465_3766520548$', '_SYSSMU236_3356150501$');


SEGMENT_NAME              BLOCKS   EXTENTS
------------------------ ----------   ----------
_SYSSMU236_3356150501$ 753016       32765
_SYSSMU465_3766520548$ 1528552       32765

通过以上信息,外面看出是两个segment的extents 过多,也就是碎片过多导致,我要做的就是减少两个segment的extents数据量解决办法有两种
a 重新建个undo表空间,使用新的undo表空间替换正在使用的,这个操作可以在线做 注意选择业务空闲时段做
b 收缩这个这个两个段,减少extents数量
这里我选择的是后一种
处理步骤如下:

1 查询隐藏参数 _smu_debug_mode记录老的值,收缩后修改会此值
  select a.inst_id,
       a.ksppinm "Parameter",
       b.ksppstvl "Session Value",
       c.ksppstvl "Instance Value"
  from x$ksppi a, x$ksppcv b, x$ksppsv c
 where a.indx = b.indx
   and a.indx = c.indx
   and a.inst_id = b.inst_id
   and b.inst_id = c.inst_id
   and a.ksppinm in ('_smu_debug_mode');
   我的系统 _smu_debug_mode的值是0 
alter system set "_smu_debug_mode"=4 scope=memory ; --0x00000004    Allow RBU operations to be executed in SMU mode

3  收缩两个segment
SQL> alter rollback segment "_SYSSMU465_3766520548$" shrink;

    Rollback segment altered.

SQL> alter rollback segment "_SYSSMU236_3356150501$" shrink;

    Rollback segment altered.

4 修改为之前的值,由于系统是一体机,需要设置为0,否则storage index不能使用
SQL> alter system set "_smu_debug_mode"=0 scope=memory ;

System altered.

5 查看收缩后两个segment的extents 数量
SQL> SELECT T.segment_name,T.BLOCKS,T.EXTENTS FROM DBA_SEGMENTS T WHERE T.segment_name IN ('_SYSSMU465_3766520548$', '_SYSSMU236_3356150501$');

SEGMENT_NAME                 BLOCKS EXTENTS
------------------------------  ---------- ----------
_SYSSMU236_3356150501$      232            29
_SYSSMU465_3766520548$      760            16

客户再次执行过程问题解决。 

总结
出现此问题的原因主要是 事务过大占用过多的undo segment 导致segment 扩展到一定的extents后不能再扩展
可以通过优化慢的SQL语句和减小事务来避免这样的问题

 





你可能感兴趣的:(ora-错误处理,ora-1628,数据库)