Czy kiedy rekord jest zablokowany w Oracle, możemy wiedzieć, który rekord jest zablokowany?

10

Kiedy rekord jest zablokowany, czy możemy wiedzieć, który jest zablokowany?

Jak mogę uzyskać rekord rowid lub coś innego?


Mogę uzyskać informacje o tym 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(+) 

Znalazłem metodę w sieci, aby uzyskać Rowid za pomocą funkcji DBMS_ROWID.ROWID_CREATE()

Ale to nie działa.

iafanda
źródło
2
Widoczne są tylko blokady, na które czeka jakiś proces, a nie blokady wstrzymane przez transakcję.
a_horse_w_no_name
@a_horse_with_no_name - v $ lock pokazuje zamki posiadane przez transakcję
Chris Saxon
@ChrisSaxon: Masz rację. Miałem na myśli fakt, że nie widać, które rzędy zostały zablokowane - powinienem był być bardziej jasny.
a_horse_w_no_name
Oracle (w przeciwieństwie do innych baz danych) nie ma żadnej wspólnej struktury blokad. To sprawia, że ​​baza danych jest skalowalna, ale z drugiej strony nie widać wszystkich blokad. Zamki są przechowywane bezpośrednio w blokach baz danych. W momencie, gdy ktoś zostanie zablokowany, tworzona jest struktura „uchwyt-kelner”. Wtedy zobaczysz tę parę V$LOCK.
ibre5041

Odpowiedzi:

13

Nie można tak naprawdę wymienić wszystkich wierszy blokowanych przez sesję. Jednak gdy sesja jest blokowana przez inną, możesz dowiedzieć się, która sesja / wiersz ją blokuje.

Oracle nie utrzymuje listy pojedynczych blokad wierszy. Zamiast tego zamki są rejestrowane bezpośrednio w samych rzędach - pomyśl o tym jak o dodatkowej kolumnie.

Możesz zobaczyć, która sesja uzyskała blokadę obiektu poprzez V$LOCKwidok, ale wyświetli to tylko informacje ogólne, a nie na poziomie wiersza.

W tym widoku możesz również sprawdzić, czy sesja jest blokowana przez inną. W takim przypadku, jeśli sesja jest blokowana przez inną sesję, informacje o wierszu są wyświetlane w V$SESSIONinformacjach.

Możesz pobrać rowid, zbudujmy przykład z 2 sesjami:

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 */

Sesja 2 czeka teraz na sesję 1. Możemy odkryć wiersz blokujący za pomocą:

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

Do dalszej lektury: opis procesu autorstwa Toma Kyte'a .

Vincent Malgrat
źródło
3

Wszystkie blokady tabel można znaleźć w bazie danych Oracle, uruchamiając następujące zapytanie

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
źródło