Quando um registro está bloqueado no Oracle, podemos saber qual registro está bloqueado?

10

Quando um registro está bloqueado, podemos saber qual deles está bloqueado?

Como posso obter o registro rowid ou outra informação?


Eu posso obter algumas informações neste sql

SELECT c.ROW_WAIT_OBJ#,c.ROW_WAIT_FILE#,c.ROW_WAIT_BLOCK#,c.ROW_WAIT_ROW#
   FROM v$locked_object a, dba_objects b, v$session c    
WHERE a.object_id = b.object_id    
    AND a.SESSION_ID = c.sid(+) 

Eu encontrei um método na web para obter rowid usando a função DBMS_ROWID.ROWID_CREATE()

Mas isso não parece funcionar.

iafanda
fonte
2
Você pode ver apenas bloqueios que algum processo está aguardando, não aqueles mantidos por uma transação.
a_horse_with_no_name
@a_horse_with_no_name - v $ bloqueio mostra os bloqueios mantidos por uma transação
Chris Saxon
@ ChrisSaxon: Você está certo. Eu estava me referindo ao fato de que você não pode ver quais linhas foram bloqueadas - eu deveria ter sido mais claro.
A_horse_with_no_name
O Oracle (ao contrário de outros bancos de dados) não possui nenhuma estrutura compartilhada para bloqueios. Isso torna o banco de dados escalável, mas, por outro lado, você não pode ver todos os bloqueios. Os bloqueios são armazenados diretamente nos blocos do banco de dados. No momento em que alguém é bloqueado, é criada uma estrutura "garçom-garçom". Então você verá esse par V$LOCK.
Ola5041

Respostas:

13

Você não pode realmente listar todas as linhas que estão sendo bloqueadas por uma sessão. No entanto, uma vez que uma sessão está sendo bloqueada por outra, você pode descobrir qual sessão / linha está bloqueando-a.

O Oracle não mantém uma lista de bloqueios de linha individuais. Em vez disso, os bloqueios são registrados diretamente nas próprias linhas - pense nisso como uma coluna extra.

Você pode descobrir qual sessão adquiriu um bloqueio em um objeto através da V$LOCKvisualização, mas isso listará apenas informações gerais, não no nível da linha.

Com essa visualização, você também pode descobrir se uma sessão está sendo bloqueada por outra. Nesse caso, se uma sessão for bloqueada por outra, as informações da linha serão exibidas nas V$SESSIONinformações.

Você pode recuperar o rowid, vamos criar um exemplo com 2 sessões:

SESSION1> create table test as select * from all_objects;

Table created

SESSION1> select rowid from test where object_name = 'TEST' for update;

ROWID
------------------
AAMnFEAAaAAALTDAAz

/* setting identifiers to help with identifying this session later */
SESSION2> exec dbms_application_info.set_client_info('012345');

PL/SQL procedure successfully completed

SESSION2> select 1 from test where object_name = 'TEST' for update;
/*  this will block */

A sessão 2 agora está aguardando a sessão 1. Podemos descobrir a linha de bloqueio com:

SESSION1> SELECT o.object_name,
       2         dbms_rowid.ROWID_CREATE (1,
       3                                  s.ROW_WAIT_OBJ#,
       4                                  s.ROW_WAIT_FILE#,
       5                                  s.ROW_WAIT_BLOCK#,
       6                                  s.ROW_WAIT_ROW#) rid
       7     FROM dba_objects o, v$session s
       8    WHERE o.object_id = s.row_wait_obj#
       9      AND s.client_info = '012345';

OBJECT_NAME     RID
--------------- ------------------
TEST            AAMnFEAAaAAALTDAAz

Para leitura adicional: uma descrição do processo por Tom Kyte .

Vincent Malgrat
fonte
3

Você pode encontrar todos os bloqueios de tabelas em um banco de dados Oracle executando a seguinte consulta

select
   c.owner,
   c.object_name,
   c.object_type,
   b.sid,
   b.serial#,
   b.status,
   b.osuser,
   b.machine
from
   v$locked_object a ,
   v$session b,
   dba_objects c
where
   b.sid = a.session_id
and
   a.object_id = c.object_id;
Baji Shaik
fonte