Oracle: Поиск заблокированной строки возвращает неверный идентификатор строки

#sql #oracle

Вопрос:

У меня есть Oracle DB 19c, которая является основой для клиентского приложения.

Когда приложение обращается к строке таблицы, оно блокирует ее, а затем приложение, запущенное с другого компьютера, больше не может получить доступ к этой записи. Я хочу выяснить, кто и на каком компьютере блокирует какую запись.

В своем исследовании я нашел следующее руководство: http://www.orafaq.com/node/854 В нем довольно хорошо перечислены шаги, которые необходимо выполнить, и, наконец, я создал следующий запрос для своих целей:

 select LCK.*,OBJ.*,SESS.*, (CASE WHEN SESS.ROW_WAIT_OBJ# > -1 THEN dbms_rowid.rowid_create( 1, obj.Object_ID, SESS.ROW_WAIT_FILE#, SESS.ROW_WAIT_BLOCK#, SESS.ROW_WAIT_ROW# ) ELSE 'NA' END) as ROWID111
from v$locked_object LCK
left join dba_objects OBJ
on LCK.OBJECT_ID = OBJ.OBJECT_ID
left join v$session SESS
on LCK.SESSION_ID = SESS.SID;
 

Моя цель-вернуть строку таблицы, которая заблокирована.

К сожалению, метод dbms_rowid.rowid_create() не генерирует правильный идентификатор строки. Я провел некоторую обратную разработку и выяснил, что…

  • идентификатор объекта, предоставляемый rovid_create (), должен быть идентификатором объекта из dba_objects
  • ФАЙЛ SESS.ROW_WAIT_FILE# указывает на правильный файл
  • SESS.ROW_WAIT_BLOCK НЕ является идентификатором блока таблицы, содержащей заблокированную запись
  • SESS.ROW_WAIT_ROW# НЕ является номером строки заблокированной записи

Похоже, что каким-то образом таблица сеансов v$не содержит информации, необходимой мне для получения правильных значений для генерации идентификатора строки….

Ответ №1:

Я всегда использую следующие инструкции в разных версиях Oracle, и у меня никогда не было никаких проблем

Получить блокирующие сеансы и связанные с ними процессы

 set lines 300
COLUMN username FORMAT A30
COLUMN osuser FORMAT A10
COLUMN machine FORMAT A30
COLUMN logon_time FORMAT A20
COLUMN PROGRAM format a20
COLUMN MODULE format a20
COLUMN sid_serial_inst format a20

SELECT level,
       LPAD(' ', (level-1)*2, ' ') || NVL(s.username, '(oracle)') AS username,
       s.osuser,
       s.sid || ',' || s.serial# || ',@'|| inst_id as sid_serial_inst,
       s.blocking_session,
       s.lockwait,
       s.status,
       s.module,
       s.machine,
       s.program,
       TO_CHAR(s.logon_Time,'DD-MON-YYYY HH24:MI:SS') AS logon_time
FROM   gv$session s
WHERE  level > 1
OR     EXISTS (SELECT 1
               FROM   gv$session
               WHERE  blocking_session = s.sid and inst_id=s.inst_id)
CONNECT BY PRIOR  s.sid || '@inst'|| inst_id = s.blocking_session || '@inst'|| inst_id 
START WITH s.blocking_session IS NULL;
 

Чтобы заблокировать строки

 set lines 200
select s.sid,do.object_name,
row_wait_obj#, row_wait_file#, row_wait_block#, row_wait_row#,
dbms_rowid.rowid_create ( 1, ROW_WAIT_OBJ#, ROW_WAIT_FILE#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW# )
from v$session s, dba_objects do
where sid in (SELECT sid FROM  GV$LOCK WHERE  request>0)
and s.ROW_WAIT_OBJ# = do.OBJECT_ID ;
 

ДЕМОНСТРАЦИЯ

Сессия 1

 SQL> create table test1 ( c1 number, c2 number );

Table created.

SQL> insert into test1 values ( 1, 1);

1 row created.

SQL> insert into test1 values ( 2,2) ;

1 row created.

SQL> commit ;

Commit complete.
 

Сессия 2

 SQL> update test1 set c1=3 where c1=2 ;

1 row updated.

SQL>
 

Затем снова в сеансе 1

 SQL> update test1 set c1=4 where c1=2 ;
 

Здесь сеанс заблокирован, ожидая, пока другой совершит фиксацию или откат, поэтому давайте запустим запрос, чтобы проверить затронутые строки

 SQL> r
  1  select s.sid,do.object_name,
  2  row_wait_obj#, row_wait_file#, row_wait_block#, row_wait_row#,
  3  dbms_rowid.rowid_create ( 1, ROW_WAIT_OBJ#, ROW_WAIT_FILE#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW# )
  4  from v$session s, dba_objects do
  5  where sid in (SELECT sid FROM  GV$LOCK WHERE  request>0)
  6* and s.ROW_WAIT_OBJ# = do.OBJECT_ID

Session-ID OBJECT_NAME                    ROW_WAIT_OBJ# ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_ROW# DBMS_ROWID.ROWID_C
---------- ------------------------------ ------------- -------------- --------------- ------------- ------------------
       601 TEST1                                1032538              1          123257             1 AAD8FaAABAAAeF5AAB