• Anderson Graf

Row Locks (TX) - Como identificar a linha bloqueada

Atualizado: Ago 18

Em um banco de dados multiusuários como o Oracle database, é necessário que exista algum tipo de bloqueio de dados para que possam ser resolvidos os problemas associados à simultaneidade, consistência e integridade de dados. Estes bloqueios são mecanismos que impedem a interação destrutiva entre as transações que acessam o mesmo recurso.


Um dos tipos de bloqueios existentes é o bloqueio (lock) de linha identificado pelo evento de espera (wait event) "enq: TX - row lock contention".


Um lock do tipo linha ocorre naturalmente sobre a linha de uma tabela, ou seja, enquanto uma linha (registro) está "alocado", nenhuma outra sessão conseguirá alterá-lo até que a transação que originou o lock chegue ao seu fim, seja por commit ou rollback.


A identificação de um lock transacional (TX) pode ser realizada de diferentes formas, aqui utilizaremos o script utllockt.sql distribuído pela própria Oracle e encontrado abaixo do $ORACLE_HOME/rdbms/admin


Montando o cenário:


SESSÃO 1:

Observe que ao final do UPDATE não foi executado commit ou rollback;


SESSÃO 2:

A sessão 2 (sid=51) ao tentar realizar a alteração da mesma linha da sessão 1 (sid=58) ficou "travada" pois a linha id=1 está bloqueada até que a sessão 1 realize um commit ou rollback do registro.


SESSÃO 3:

A sessão 3 (sid=56) ao tentar alterar a mesma linha que a sessão 2 (sid=51) também ficou presa, pois a sessão 2 ainda não concluiu sua transação, desta forma existe a sessão 2 aguardando a sessão 1 e a sessão 3 aguardando a sessão 2 conforme árvore de bloqueio abaixo:


SESSÃO 4:

Cenário de bloqueio:







Identificando as linhas bloqueadas:


Sempre que uma sessão fica aguardando um lock transacional (row lock – TX), algumas informações adicionais são populadas na v$session:



Utilizando-se destes dados é possível identificar o ROWID da linha bloqueada.


O ROWID é uma pseudocolumn que representa o endereço de cada linha de uma tabela. Os valores desta pseudocoluna são strings que podem conter os caracteres A-Z, a-z, 0-9 e o sinal de mais (+) e a barra (/).

Os rowids são formados pelas seguintes informações:

  • Data block: Bloco de dados que contém a linha;

  • Row: Linha no bloco de dados;

  • Database file: Arquivo de dados que a linha;

  • Data object number: Número de identificação do objeto.


Agora basta utilizar o pacote DBMS_ROWID para interpretar os conteúdos de rowid. As funções do pacote extraem e fornecem informações sobre os quatro elementos rowid listados acima.

Como as colunas ROW_WAIT_* da v$session são populadas apenas quando uma sessão está aguardando alguma transação, podemos identificar a rowid (endereço da linha) que as sessões 2 (sid=51) e 3 (sid=56) estão aguardando.


Linha bloqueada da sessão 2:

Linha bloqueada da sessão 3:

Neste exemplo (cenário), como não foi utilizado bind variables nas operações DML é possível identificar também o valor bloqueado pelo próprio texto sql da instrução:


Com a utilização de bind variables a instrução retornada seria similar a:


update teste set id=:b2 where id=:b1

A identificação da instrução também é importante para saber quais colunas estão sofrendo alterações, pois a linha retornada pelo rowid pode conter várias colunas diferentemente do exemplo onde a tabela possuía apenas uma coluna.




Referências:


https://docs.oracle.com/database/122/CNCPT/data-concurrency-and-consistency.htm#CNCPT1313

https://docs.oracle.com/database/122/REFRN/V-SESSION.htm#REFRN30223

https://docs.oracle.com/database/122/SQLRF/Data-Types.htm#SQLRF50998

91 visualizações0 comentário