Browse By

Library cache: mutex X e agora ?

Olá amigos,

Hoje vou escrever resumidamente sobre um evento (Library cache: mutex X) que encontro em alguns ambientes além também de ouvir comentários de alguns amigos sobre os seus. Problemas que podem gerar uma pequena dor de cabeça e dependendo do processo e análise, sua correção pode como não, ser rápida mas até chegarmos nesse ponto, um certo desconforto talvez ja tenha sido criado. Estamos falando da famosa (uma das) concorrências mais importantes do banco de dados.

Essas concorrências chamadas de Latchs em versões <= 10  e mutexes  na versão >= 10g (na versão 10g existiam as latchs (foram melhor desenvolvidas do que as versões anteriores) e também foram adicionadas alguns novos mecanismos conhecidos como mutex, onde na versão 11g ja estamos trabalhando com força total neles ),  ja estão bem explicadas (os mutexes por estarem mais fortes na versão 11g, encontram-se ainda com pouco material em comparação das versões anteriores que usavam latchs) em vários materiais, artigos, blogs, livros, mas creio que um entendimento simples e básico possível seria:

Latchs seriam como o mecanismo de “lock” que conhecemos (em um nivel mais baixo) a nivel de memória fazendo com que esse fator deixe-a muito mais rápida, tanto para ser adquirida quanto para ser liberada. Elas servem para proteger a estrutura/pedaços de memória da nossa instancia, não deixando que dois ou mais processos acessem ou modifiquem os mesmos objetos ao mesmo tempo, protegendo a integridade, sendo assim, quando um objeto é localizado, a latch (trava) faz o “lock” até o período de utilização desse objeto pela sessão, utilizando instruções hardware-atomic CAS (compare and swap)  sobre algumas plataformas (Intel creio que seja diferente) e assim que finalizam, são liberadas para que possam fazer o mesmo processo sobre outras sessões. Com os mutexes o mesmo processo ocorre de uma maneira mais avançada deixando ele ainda mais rápido que as latchs. As latchs são adquiridas e liberadas sem interação do SO.

Elas não possuem uma fila “FIFO” como o lock transacional ( essa seria uma outra funcionalidade que as deixam mais rápidas)  mas em alguns testes e algumas documentações que encontrei a algum tempo atrás, notei que existe uma “certa” fila (logicamente bem(muito) rápida que uma fila de lock transacional) a ser seguida nas novas versões, mas esse assunto é para ser detalhado em um outro artigo que contenham pelo menos umas 3 páginas, mas não é o caso agora.

Desculpem pela explicação simplória e bem “lixenta” mas se fosse para colocar todos os mecanismos/algoritmos das latchs e mutexes o artigo ficaria muito extenso, comentando sobre o inicio para adquiri-las, sobre gets, spining, processo post, processo reliable,  explicando sobre latchs que residem tanto na shared_pool como no buffer cache (buffer cache chains, *lru*) e assim por diante mas, para uma abordagem um pouco maior recomendo a leitura dos seguintes notes 22908.1  latchs e 1005801.1 para mutexes, fora nosso amigo na alegria e na tristeza, na saúde ou na doença, google.rs.

Lembrando que as latchs/mutexes podem ocorrer tanto por algum bug no Software do banco de dados como em má programação/lógica de uma aplicação e assim por diante, então, para descartar a possibilidade de BUG em seu ambiente, recomendo a leitura dos notes 5928271.8 7307972.8 9398685.8 9312879.8 9530750.8 e o principal note na minha opinião: 727400.1

No meu caso o amigo METALINK mostrava que possívelmente trataria-se de um BUG 9239863 mas a versão instalada no meu ambiente era a 11.2.0.3, teoricamente conteria o FIX que o note informava, então, isso começava aparentar como má logica/programação ou um sistema na qual sua arquitetura não estava preparada para um grande crescimento(estranhamente).

A concorrência aumentava sobre objetos que o software de benchmark (ou o seu sistema) acessava conforme a quantidade de sessões eram adicionadas, dessa forma comecei a perceber que se tratava de uma possível concorrência sobre acesso, mas acesso ao que ? logon/logoff ? acessos a objetos ?.  Voltando ao case:

Os testes foram realizados sobre um ótimo servidor, resumo das configurações: SO:Oracle Enterprise Linux 6.1 X86_64 – CPU’s: 80 – Threads per Core:2 – Core(s) per Socket:10 – CPU Socket(s):4 – CPU Mhz: 1064.000 L1d cache:32k L2 cache:256k L3 cache:24576k e 128GB de ram.

Fazendo o benchmark com uma ferramenta que já postei aqui (já que a aplicação não possui uma versão para teste/sizing e etc) percebi que não estava alcançando números interessantes (TPS) com um servidor dessa categoria. Após conectar no velho e bom sqlplus notei que a wait sobre o evento:  Library cache: mutex X era a top consumidora como mostrado abaixo, sobre um gráfico para melhor visualização:

Para os adpetos do Oracle Enterprise Manager, ele ficou assim:

O AWR (snapshot de 30 minutos) afirma os principais waits desse período:

Muitas sessões ativas aguardando pelo evento Library cache: mutex X. Isso fez com que eu não conseguisse alcançar os valores esperados no benchmark em TPM e logicamente, trazendo lentidão sobre essas sessões então, a única maneira de resolver isso seria diminuindo/eliminando o tempo de resposta sobre esse evento.

Analisando o ambiente identifiquei que haviam concorrências sobre 3 objetos no banco de dados. Segue query abaixo que utilizei para encontrar os top’s library cache objetos acessados.

col objname format a60
col type FOR a15
col LOCK_SUM FOR 99999999999
col PIN_SUM FOR 99999999999
col EXEC FOR 99999999999
col NAMESPACE FOR 999
set linesize 1000
select * from (
   select kglhdadr ADDR,
          kglobt09,
          substr(kglnaobj,1,80) objname,
          kglnahsh hashvalue,
          kglobtyd type,
          kglobt23 LOCK_SUM,
          kglobt24 PIN_SUM,
          kglhdexc EXEC,
          kglhdnsp NAMESPACE
       from x$kglob
  order by kglobt24 desc)
where rownum <= 100;

O resultado foi:

Podemos ver que o object TYPE chamado INTEGER_RETURN_ARRAY (objeto do benchmark) esta com um valor muito alto no tempo “lockado” e na quantidade de “pin’s” acessos. Inclusive o objeto dbms_application_info (package do proprio Oracle) também estava com um valor muito alto,  possivelmente era utilizado para setar as informações de cada sessão no banco de dados.

Podemos afirmar isso analisando as dba_hist*, ASH e etc. Nesse caso vamos fazer um select sobre a view v$active_session_history para analisarmos o que ocorreu recentemente em nosso ambiente:

col sample_time for a20
col session_id for a999999
col event format a25
col location_id for 99
col mutexobject for a60
set pagesize 1000

SELECT to_char(sample_time,'hh24:mi:ss') sample_time,
 session_id,
 sql_id,
 event,
 p1 IDN,
 FLOOR(p2/POWER(2,4 * 8)) blocking_sid,
 FLOOR (p3/POWER (2,4 * 8)) location_id,
 CASE WHEN (event LIKE 'library cache:%' AND p1 <= power(2,17)) THEN  'library cache bucket: '||p1
 ELSE  (SELECT substr(kglnaobj,1,60) FROM x$kglob WHERE kglnahsh=p1 AND (kglhdadr = kglhdpar) and rownum=1) END mutexobject
 from v$active_session_history
 WHERE p1text='idn' AND session_state='WAITING'
 ORDER BY sample_time;

O resultado foi:

Existiam outras sessões esperando sobre os objetos dbms_application_info mas no nosso caso o top-1 seria o objeto TYPE já identificado acima chamado INTEGER_RETURN_ARRAY.

Ok, Agora que identificamos os principais objetos que estão em concorrência de acesso devido a quantidade de sessões  (hot objects), o que faremos ? O código é fechado, impossível de se alterar algo!!! Como mudar a forma que as sessões acessam os mesmos objetos em tão pouco tempo ? Acho que essas são perguntas que vc ja deve ter feito em algum momento da sua vida, mas logo adiante irei mostrar que existe uma saída.

Bom, sabemos que as contenções estavam sobre esses objetos então, se de alguma forma conseguissimos criar outras cópias para fazer um tipo “load balance” a nivel de objetos, creio que essa concorrência diminuiria muito, já que existiriam outros objetos identicos para serem utilizados, correto ?

Existem algumas formas interessantes de se fazer isso porém utilizando parametros hidden ( “_” ) como _kgl_hot_object_copies em complemento com o _kgl_debug (note 1388197.1 ) mas sabemos que a utilização de parametros ocultos acabam não sendo uma boa opção quando necessitamos do suporte da Oracle, ou seja caso vc esteja com problemas e o suporte da Oracle identifique que parametros ocultos estão configurados sem a permissão deles, vc automaticamente perderá o suporte até que arrume tudo novamente, é um processo complicado por isso recomendo somente a utilização em bases de testes, estudos e se em produção, somente com o aval do MOS. (Mas não deixa de ser uma saída).

A partir da versão do Oracle 11.2.0.2 se me lembro bem, a Oracle introduziu uma nova procedure chamada dbms_shared_pool.markhot . Creio que só pelo nome muitos dba’s ja devem estar imaginando algumas coisas, mas é isso mesmo, com esse processo o Oracle marca os objetos como HOT fazendo com que sejam criadas CÓPIAS em memória do mesmo objeto com o mesmo nome, mesmo código do mesmo esquema, muito interessante. Já podemos imaginar o seguinte, se com um único objeto minha concorrência estava muito alta, criando algumas cópias identicas dele, teoricamente nossa concorrência deveria cair ja que as sessões poderiam dividir os acessos a esses “novos” objetos. Vamos aos testes:

Vou marcar os principais objetos encontrados na analise acima como hot:

exec dbms_shared_pool.markhot(‘SYS’,’DBMS_APPLICATION_INFO’,1); << Aqui coloco o numero do namespace da packege que seria 1 = Especificação e 2 = Body

Executo o benchmark com a mesma quantidade de sessões e tempo, o resultado foi:

Pelo Oracle Enterprise Manager:

Podemos ver já nos primeiros 20 minutos que o wait Library cache Mutex X não é mais o nosso top event .

Olhando por um outro gráfico dos principais waits desse período temos :

O top wait realmente não seria mais a concorrência de Mutexes. Olhando pelo AWR (snapshot 30 minutos) também temos os mesmos resultados:

Com isso obtivemos um ganho muito grande na quantidade de transações por segundo cerca de 700 a 1000 a mais.

Para desfazer o processo é muito simples, apenas executando o procedimento dbms_shared_pool.unmarkhot

Bom pessoal, tentei fazer um artigo pequeno e de fácil entendimento já que o meu tempo também esta muito escasso mas vou reforçar aqui o seguinte, as concorrências de latchs/mutexes podem ocorrer por N fatores, alguns ja descritos acima, mas existem muitos outros. O caso exemplificado aqui foi sobre o evento Library cache: mutex X SOBRE concorrência de HOT OBJECTS na library cache, mas esse mesmo evento pode ocorrer por outros fatores além de hot objects, ok ?

Lembrando que existem as views totalmente relacionadas aos mutexes, seriam:  v$mutex_sleep para descobrir o tipo de mutex e a “location/where” que seria uma informação muito importante para se descobrir de qual parte do “código”/função do oracle esta sofrendo a contenção e a view v$mutex_sleep_history que mostra os sleeps mais recentes. Essas views podem auxiliar muito para descobrir quais tipos de problemas sua contenção por mutex esta sofrendo.

Espero ter ajudado…

Forte abraço

 

13 thoughts on “Library cache: mutex X e agora ?”

  1. Anselmo Ribeiro says:

    Muito bom o tema abordado
    Bem objetivo e claro
    Ajudará muito como linha de pesquisa no nosso dia-a-dia
    Parabéns Wellington!!

    1. admin says:

      Obrigado Anselmo !!!

  2. André Mercanti says:

    Wmon,

    Parabens pelo artigo, do jeito que eu gosto, indo aos pontos e com explicações otimas.
    Sempre com seus ensinamentos de qualidade, o artigo ficou muito interessante.
    Sucesso!

    Forte Abraço.

    André Mercanti

    1. admin says:

      Muito obrigado André!!!

  3. Luciano Rocha says:

    Parabéns, excelente artigo e me ajudou muito por aqui.

    1. admin says:

      Muito obrigado Luciano.

      Forte abraço

  4. Eli Dias says:

    Olha que dahora, parabéns, show de bola!

    1. admin says:

      Fala Eli! Sumidão…Depois que vira dba MASTER esquece dos normais…

      abs

  5. Hudson says:

    Olá,

    Muito bom mesmo o artigo e me ajudou a encontrar esse problema aqui, porém fiquei com uma dúvida, no seu caso o contenção estava no objeto DBMS_APPLICATION_INF, porém no meu aparece contenção em cursor mesmo e no resultado do select ele retorna o OBJNAME a parte do sql que está com contenção, como posso aplicar nesse caso?

    1. admin says:

      Olá Hudson,

      Vamos ver se entendi direito. As informações retornadas pela query mostram o top problema com o TYPE = CURSOR, certo ? Nesse caso vc gostaria de aplicar esse procedimento para o CURSOR também, correto ?

      Com o resultado da query em mãos, vc precisa encontrar o valor HASH COMPLETO do cursor, para isso, execute a query abaixo informando o HASH_VALUE que você ja possui da query anterior, ex:

      select kglnahsv,kglnaobj from x$kglob
      where kglnahsh=2085103097 — Seu valor hash
      and kglhdadr =kglhdpar;

      Coloque o resultado da coluna kglnahsv no processo abaixo, deixando o NAMESPACE como 0 pois seria um CURSOR, ex:

      exec dbms_shared_pool.markhot(HASH=>’3d1d3e904db2c2b419f591841c128d54′,NAMESPACE=>0);

      Espero ter ajudado.

      Forte abraço

  6. Hudson says:

    Era isso mesmo, muito obrigado Wellington.

  7. Muneer Alam says:

    Hi

    I must say its an excellent article.

    A few days ago I hotmarked some of the objects using markot procedure. Now i need to unmark them. For that i need to use unmarkhot procedure but I am not sure of what objects did I mark hot. is there anyway I could find that out and then unmark them.

    thanks
    muneer

    1. admin says:

      Tks the for comments.
      As we know, the objects are in memory until the instance is restarted where Markhot procedure should be exeuctado again.
      You have 2 options, restart the instance to remove all objects marked as hot (I believe this is little unlikely) or use the PROPERTY column of V$DB_OBJECT_CACHE view to find objects, looking for possible values include hot or hotcopy when the library cache hot copy feature is used using DBMS_SHARED_POOL.MARKHOT and after that is easy to use UNMARKHOT procedure.

      Regards,

Leave a Reply to André Mercanti Cancel reply

Your email address will not be published. Required fields are marked *