Oracle SQL - SELECT查询锁定索引并阻止DML会话

tod*_*not 5 sql oracle concurrency plsql oracle11g

我们在生产中发生了一些非常奇怪的锁定.我们设置了一个PL/SQL脚本,用于查找已锁定超过5秒的对象并向我们发送警报电子邮件.

下面是该脚本的光标:

select l.sid, trunc(l.id1 / power(2, 16)) rbs,
    bitand(l.id1, to_number('ffff', 'xxxx')) + 0 slot,
    l.id2, l.lmode, l.request, l.ctime, l.block,
    substr(v.osuser, 1, 12) osuser,
    substr(v.machine, 1, 15) machine,
    substr(v.module, 1, 12) module,
    decode(v.blocking_session_status||l.block, 'VALID0',
           dbms_rowid.rowid_create(1, v.row_wait_obj#, v.row_wait_file#,
                       v.row_wait_block#, v.row_wait_row#), '.') lrow,
    o.object_name,
    decode(v.sql_id, null, v.prev_sql_id, v.sql_id) sql_id,
    o.owner
from v$lock l, v$session v, all_objects o
where l.sid = v.sid
  and v.row_wait_obj# = o.object_id(+)
  and l.ctime > 5 and l.type = 'TX' and (l.request = 6 or l.block = 1)
order by 2, 3, 4, 8 desc, 7 desc;
Run Code Online (Sandbox Code Playgroud)

我们今天得到了锁定警报:

SID  TRANS-ID        L-TYPE  CTIME  BLOCK OSUSER     MACHINE         MODULE        SQLID            ROWID            OBJECT
---- --------------- ------- ------ ----- ---------- --------------- ------------ ------------- ------------------ --------------------
669  132,11,40475    6/0     70     1     userpr1     serv1023       userpr1-00002 fbnhs4gd9a7yn .                  IDX_005
1133 132,11,40475    0/6     62     0     userpr1     serv1023       userpr1-00000 f0gm2rx85qjja AAAgOuAAFAAD04TAAW ITEMST
924  132,11,40475    0/6     53     0     userpr1     serv1023       userpr1-00002 f0gm2rx85qjja AAAgOuAAFAAD04TAAW ITEMST
927  132,11,40475    0/6     27     0     userpr1     serv1023       userpr1-00001 f0gm2rx85qjja AAAgOuAAFAAD04TAAW ITEMST
Run Code Online (Sandbox Code Playgroud)

因此,从上面我们可以看到fbnhs4gd9a7yn会话的sqlid 669已经锁定了索引IDX_005并阻塞了剩余的其余会话.

现在最奇怪的部分:

  1. SQLID fbnhs4gd9a7yn只是一个SELECT查询(甚至不是SELECT FOR UPDATE)
  2. 索引IDX_005与表没有连接,ITEMST但它会阻止剩余的3个会话,ITEMST无论如何都会更新

所以我的问题是:[1]是如何发生的,为什么它会阻止对表的更新ITEMST

这可能是Oracle中的一个错误吗?我们正在使用Oracle 11.2.0.4企业版,顺便说一句.

Jus*_*ave 5

sql_id您的查询返回可能会或可能不会与实际获取锁的查询.

例如,在SID 669中,如果我更新ITEMST然后运行查询但我没有提交我的查询update,您会看到669正在运行一个SELECT语句并且它持有一个锁.这是会议实际获得锁定的早期UPDATE(或者INSERT其他).只是没有一种简单的方法可以看到会话已经完成的早期查询获得了其他会话正在等待的锁定.