Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2802719
  • 博文数量: 389
  • 博客积分: 4177
  • 博客等级: 上校
  • 技术积分: 4773
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-16 23:29
文章分类

全部博文(389)

分类: Oracle

2014-12-05 20:05:12

                                Curosr相关的Mutex等待事件

    从oracle官方手册关于mutex的定义来看,mutex是一个低级别的锁机制,用来保护SGA中
的共享对,像防止被老化出去.

A mutual exclusion object (mutex) is a low-level mechanism that prevents an object in memory from aging
out or from being corrupted when accessed by concurrent processes. A mutex is similar to a latch,
but whereas a latch typically protects a group of objects, a mutex protects a single object

                                                               ---来自12C的concept

但是这里面有几个内容:究竟什么是低级别?保护SGA中的什么内容?


  在现有的版本中muext主要有以下几个等待事件:cursor:pin S, cursor:pin X,cursor:mutex S;cursor:mutex X
cursor:pin S wait X,library cahce:mutex X, library cache:mutex S.

   Mutex本身有可能是和被保护对像在一起,也可能是一个单独的位置.

  首先我们来看SQL的处理过程,又是从官档上摘下的内容,当一个服务器进程接收到一个SQL后,会在
共享池中进行查找,如果没查找,就会做一个hard parse,那hard parse又做了一些什么事呢?

When an application issues a SQL statement, the application makes a parse call to the database
to prepare the statement for execution. The parse call opens or creates a cursor, which is a handle for
 the session-specific private SQL area that holds a parsed SQL statement and other processing information

general stages of SQL processing: parsing, optimization, row source generation, and execution. Depending
on the statement, the database may omit some of these steps
                                                                       ---来自12C的concept

 根据官档说的,会进行语法分析,语义分析,然后进行优化,生成执行计划.这一系列的最终成果在共享
池中反映就是生成一个SQL Cursor。

   这个Cursor又可以分为两部分,一个是Parse Cursor,一个Child Cursor.Parse Cursor存放的是sql文
本的信息,而Child Cursor存放的是动态信息,比如环境变量,优化器设置和执行计划等等.当另一个相同的
相同SQL的发布时, Parse Cursor可以被共享,但是Child Cursor不一定能被共享.

   当第一次SQL生成一个Parent和Child的时候,会等待cursor:pin X来保护自己请求的对像结构,防
止另一个会话做相同的事.当试图在一个Parent Cursor下构建Child Cursor时会在Parent上请求一个
Mutex X时,产生等待事件cursor: mutex X.

 通过在两个不同的会话分别执行以下sql,假设cursor_sharing 为exact.

 

会话1
declare
i int;
j int;
begin
    while (true)
        loop
            i:=i+1;
            select i into j from dual;
         end loop;
      end;

会话2
declare
i int;
j int;
begin
    while (true)
        loop
            i:=i+1.1;
            select i into j from dual;
         end loop;
      end;

可以观察到很频繁的cursor:mutex X的等待.

SQL> select sid,event from v$session_wait
  2  where wait_class<>'Idle'
  3  /

       SID EVENT
---------- ----------------------------------------------------------------
       207 cursor: mutex X
       582 cursor: mutex X

在开始的时候会对Parent cursor进行一个检查,会在该Parent cursor上的Mutex上等待,该等待事件
是cursor:mutex X.当发现系统中cursor:mutex X过高时,请检查AWR中的Hard Parse和平常是不是有很大变化.

  当要真正执行一个语句时,在共享池中的形式是Cursor,这个时候需要把Cursor Pin住。以防止Cursor
被老化出去.主要的等待事件就是cursor:pin S.但是


会话1
declare
i int;
j int;
begin
    while (true)
        loop
            i:=i+1;
            select i into j from dual;
         end loop;
      end;

会话2
declare
i int;
j int;
begin
    while (true)
        loop
            i:=i+1;   --与前例此处不同
            select i into j from dual;
         end loop;
      end;
 
摸拟两个话同时反复执行相同的语句,这时候可以观察到很频繁的cursor:pin S等待.


SQL> select sid,event from v$session_wait
  2  where wait_class<>'Idle'
  3  /

       SID EVENT
---------- ----------------------------------------------------------------
       207 cursor: pin S
       582 cursor: pin S


cursor:pin S是只读方式去获得mutex,只是需要去更改一个ref的值,所以也形成争用.我们知道
ref就是内存中一个地址,可以看出更快的cpu和内存总线会得到速度更快哦.即使单个会话本身也
会去在这个事件上等等.相比硬件在很多时候无法改变了,只有去优化热的对像.比如人为的打散
sql语句.

第一个会话

 declare
  i int;
  j int;
   begin
      while (true)
          loop
               i:=i+1;
                select /*+ a */ i into j from dual;  --修改这里
             end loop;
         end;
   /

第二个会话
 declare
  i int;
  j int;
   begin
      while (true)
          loop
               i:=i+1;
                select /*+ b */ i into j from dual;  --修改这里
             end loop;
         end;
   /


 
SQL> run;
 
       SID EVENT
---------- ----------------------------------------------------------------
       207 latch: shared pool
       582 latch: shared pool

产生大量的latch争用了,看来真是一波平另一波起.

AWR中mutex出现在top 5事件中的常见原因的有:硬解过多;high version count;oracle bug,
shared pool过小等

另外还有两个library cache的mutex待以后再讨论

 

 

 

 

阅读(3889) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~