故障处理】队列等待之enq: US - contention案例

来源:这里教程网 时间:2026-03-03 17:56:04 作者:

1      BLOG  文档结构图

wps6E72.tmp   

 

2      前言部分

2.1      导读和注意事项

各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,  ~O(∩_∩)O~ 

① enq: US - contention  等待事件的解决

② 一般等待事件的解决办法

③ 队列等待的基本知识

  Tips:

① 本文在  ITpub    http://blog.itpub.net/26736162  )、博客园  (  http://www.cnblogs.com/lhrbest  )和微信公众号(  xiaomaimiaolhr  )有同步更新

② 文章中用到的所有代码,相关软件,相关资料请前往小麦苗的云盘下载(  http://blog.itpub.net/26736162/viewspace-1624453/ 

③   若文章代码格式有错乱,推荐使用搜狗    360  或QQ  浏览器,也可以下载  pdf  格式的文档来查看, pdf  文档下载地址:  http://blog.itpub.net/26736162/viewspace-1624453/  ,另外  itpub  格式显示有问题,可以去博客园地址阅读

④   本篇  BLOG  中命令的输出部分需要特别关注的地方我  都用  灰色背景和粉红色字体  来表  示,比如下边的例子中,  thread 1  的最大归档日志号为 33   thread 2  的最大归档日志号为 43  是需要特别关注的地方;而命令  一般使用  黄色背景和红色字体    注;对代码或代码输出部分的注  释一般采用  蓝色字体  表示 

 

本文如有错误或不完善的地方请大家多多指正,  ITPUB留言或QQ皆可,您的批评指正是我写作的最大动力。

 

3      故障分析及解决过程

 

3.1      故障环境介绍

 

项目

source db

db   类型

RAC

db version

11.2.0.4.0

db   存储

ASM

OS版本及  kernel  版本

AIX 64位   7.1.0.0

 

3.2      故障发生现象及报错信息

最近系统做压测,碰到的问题比较多,今天同事发了个  AWR  报告,说是系统响应很慢,我简单看了下,简单分析下吧:

wps6E83.tmp   

270分钟时间而  DB Time   2000  多分钟, DB Time  太高了,负载很大,很可能有异常的等待事件,系统配置还是比较牛逼的。

wps6E84.tmp   

事务量很大,其它个别参数有点问题,不一一解说了。  等待事件很明显了:

wps6E85.tmp   

AWR的其它部分就不分析了,首先  这个等待事件:  enq: US - contention  比较少见,查了一下  资料,有点收获:

SELECT     *     FROM   V$EVENT_NAME   WHERE     NAME     =     'enq: US - contention'  ;

wps6E86.tmp   

   SELECT     *     FROM   v$lock_type d   WHERE   d.TYPE  =  'US'  ;

wps6E87.tmp   

"enq: US - contention"  ,这个 event  说明事务在队列中等待 UNDO Segment  ,通常是由于 UNDO  空间不足导致的。

在对此事件说明之前,需要理解在使用  AUM   atuomatic undo management  )时,回滚段在何时联机或脱机。 AUM   RBU   rollback segment management  )不同,回滚段的管理    O  racle  自动完成的。使用 AUM  时,回滚段的联机或脱机的时刻如下:

1  )在执行 alter database open  的时候将回滚段联机

2  )通过 alter system set undo_tablespace=xxx   修改撤销表空间时,将原来的回滚段脱机后,再将新的回滚段联机。

3  )通过 SMON  ,自动脱机或者联机回滚段,如果一段时间内,事务量增加,联机状态的回滚段也会增加,一段时间内若是没有实物或事务减少,回滚段就会被 smon  进程脱机。

为了同步将回滚段联机或脱机的过程,执行该工作的服务器进程或后台进程应获得  US  锁,每个回滚段非配一个 US  锁, ID1=Undo segment#  。若在获得 US  锁的过程中发生争用,则等待 enq   US-contention  事件。服务器进程应该在开始事务时分配到回滚段,但如果不存在可用的回滚段时,应该创建新的回滚段或将脱机状态的回滚段联机。在实现此项工作期间,服务器进程为了获得 US  锁而等待,等待占有可用回滚段。

这是  oracle10g  中开始出现的 bug(   11.1.0.7  中仍有这个 BUG)  ,当因为系统 activity  增加或者降低的时候, oracle SMON  进程会自动 ONLINE  或者 OFFLINE rollback segments  。这样导致某些与 undo segments  相关的 latch  或者 enqueue   hold  住太长时间,导致系统很多活跃 session  都开始等待 enq: US - contention  。可以同时使用以下解决方法  :

1.   设置 event   SMON  不自动 OFFLINE  回滚段

1
alter  system  set  events  '10511 trace name context forever, level 1' ;

 

2.   设置参数 _rollback_segment_count   :表示有多少 rollback segment  要处于 online  的状态;可以将该数值设置为数据库最繁忙的时候的回滚段数目。

1
alter  system  set  "_rollback_segment_count" =1000 SID= '*' ;

这里以    _    开头的为隐藏参数,通过  show parameter   是看不到的,可以通过以下语句:

1
2
3
4
select  a.ksppinm  name , b.ksppstvl value, a.ksppdesc description
from  xksppia,xksppia,xksppcv b
where  a.indx = b.indx
and  a.ksppinm  like  '%_rollback_segment_count%' ;

 

3.  undo autotune bug  多多。最好 disable 

alter system set "_undo_autotune"= false;

这种方法就是关闭了  UNDO  的自动调整功能,  同时  也能解决掉  UNDO  表空间会在很长时间都一直保持着使用率是接近 100%  的问题。

 

4.    有一个  patch: A fix to bug 7291739 is to set a new hidden parameter, _highthreshold_undoretention to set a high threshold for undo retention completely distinct from maxquerylen.

alter system set "_highthreshold_undoretention"=;

 

5.     增加undo  表空间

alter tablespace UNDOTBS1 add datafile '+DATA1' size 30G;

 

6.     设置undo表空间的  NOGUARANTEE

select tablespace_name, retention from dba_tablespaces where tablespace_name like 'UNDO%';

ALTER TABLESPACE UNDOTBS RETENTION NOGUARANTEE;

 

7.     减少UNDO_RETENTION  的时间

SQL> show parameter undo

NAME                                  TYPE         VALUE

------------------ ---------------------- --------

undo_management                     string        AUTO

undo_retention                      integer       10800

 

8.     重启数据库节点

 

3.3      故障分析及解决

我们查询  ASH  视图看看当时的情况:

   SELECT   D.SQL_ID  ,  CHR  (  BITAND  (  P1  ,     -  16777216  )     /     16777215  )     ||

          CHR  (  BITAND  (  P1  ,     16711680  )     /     65535  )   "Lock"  ,

          BITAND  (  P1  ,     65535  )   "Mode"  ,     COUNT  (  1  ),  COUNT  (  DISTINCT   d.session_id   )

    FROM   DBA_HIST_ACTIVE_SESS_HISTORY D

   WHERE   D.SAMPLE_TIME   BETWEEN   TO_DATE  (  '2016-09-07 17:39:44'  ,     'YYYY-MM-DD HH24:MI:SS'  )     AND

       TO_DATE  (  '2016-09-07 22:13:41'  ,     'YYYY-MM-DD HH24:MI:SS'  )

     AND   D.EVENT   =     'enq: US - contention'

   GROUP     BY   D.SQL_ID  ,(  CHR  (  BITAND  (  P1  ,     -  16777216  )     /     16777215  )     ||

          CHR  (  BITAND  (  P1  ,     16711680  )     /     65535  )),(  BITAND  (  P1  ,     65535  ));

wps6E98.tmp   

LOCK为  US   MODE   6  ,看看具体的 SQL  内容:

   SELECT   A.SQL_TEXT  ,   A.EXECUTIONS  ,   A.MODULE  ,   A.SQL_ID

   FROM   V$SQL A

WHERE   A.SQL_ID   IN     (  '5ww8x9u15a90y'  ,

   'ayngk81z8fh0m'  ,

   '1cmnjddakrqbv'  ,

   '26ad9zvt5xgb3'  );

wps6E99.tmp   

看看时间段是哪个区间:

SELECT   D.SQL_ID  ,   TO_CHAR  (  D.SAMPLE_TIME  ,     'YYYY-MM-DD HH24:MI'  ),     COUNT  (  1  )

    FROM   DBA_HIST_ACTIVE_SESS_HISTORY D

   WHERE   D.EVENT   =     'enq: US - contention'

     AND   D.SQL_ID   IN     (  '5ww8x9u15a90y'  ,     '26ad9zvt5xgb3'  )

   GROUP     BY   D.SQL_ID  ,   TO_CHAR  (  D.SAMPLE_TIME  ,     'YYYY-MM-DD HH24:MI'  );

wps6E9A.tmp   

看来问题几种在这  2分钟之内。  基本都是对同一个表做插入或者更新操作:

   SELECT     DISTINCT   D.CURRENT_OBJ#

     FROM   DBA_HIST_ACTIVE_SESS_HISTORY D

    WHERE   D.SAMPLE_TIME   BETWEEN

        TO_DATE  (  '2016-09-07 17:39:44'  ,     'YYYY-MM-DD HH24:MI:SS'  )     AND

        TO_DATE  (  '2016-09-07 22:13:41'  ,     'YYYY-MM-DD HH24:MI:SS'  )

      AND   D.EVENT   =     'enq: US - contention'

    GROUP     BY   D.CURRENT_OBJ#  ;

SELECT     *     FROM   DBA_OBJECTS a   WHERE   a.object_id   IN      (  '87620'  ,  '87632'  ,  '87663'  ,  '87667'  ,  '87686'  ,  '87684'  ,  '87688'  ,  '87626'  ,  '87646'  ,  '87642'  ,  '87639'  ,  '87661'  ,  '87628'  ,  '87675'  ,  '87643'  ,  '87677'  ,  '87660'  ,  '87631'  ,  '87629'  ,  '87668'  ,  '87682'  ,  '87685'  ,  '87654'  ,  '87640'  ,  '87627'  ,  '87636'  ,  '87664'  ,  '87655'  ,  '87645'  ,  '87637'  ,  '87669'  ,  '87673'  ,  '87666'  ,  '87634'  ,  '87644'  ,  '87672'  ,  '87648'  ,  '87649'  ,  '87662'  ,  '87651'  ,  '87641'  ,  '87653'  ,  '87659'  ,  '87680'  ,  '87681'  ,  '0'  ,  '87625'  ,  '87670'  ,  '87658'  ,  '87674'  ,  '87671'  ,  '87633'  ,  '87679'  ,  '87647'  );

wps6E9B.tmp   

 

可以看到操作的表是一个分区表。

解决方案:

alter tablespace UNDOTBS1 add datafile '+DATA1' size 30G;

alter system set events '10511 trace name context forever,level 1';

ALTER SYSTEM SET "_rollback_segment_count"=1000 SID='*';

 

执行之后经过开发进行压测,已经没有该等待事件的产生了:

SELECT   D.SQL_ID  ,   TO_CHAR  (  D.SAMPLE_TIME  ,     'YYYY-MM-DD HH24:MI'  ),     COUNT  (  1  )

    FROM   DBA_HIST_ACTIVE_SESS_HISTORY D

   WHERE   D.EVENT   =     'enq: US - contention'   

   GROUP     BY   D.SQL_ID  ,   TO_CHAR  (  D.SAMPLE_TIME  ,     'YYYY-MM-DD HH24:MI'  );

相关推荐