2016-12-09 36 views
4

我们在生产中发生了一些非常奇怪的锁定。我们已经建立了一个PL/SQL脚本,用于查找被锁定时间超过5秒的对象并向我们发送警报电子邮件。Oracle SQL - SELECT查询锁定索引并阻止DML会话

下面是该脚本的光标:

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; 

而我们今天拿到了警惕锁:

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 

所以从上面,我们可以观察到会议669那SQLID fbnhs4gd9a7yn已锁定索引IDX_005并阻止其余的剩余会话。

现在到了最离奇的部分:

  1. SQLID fbnhs4gd9a7yn只是一个SELECT查询(甚至不是一个SELECT FOR UPDATE)
  2. 指数IDX_005具有表ITEMST没有什么联系,但块中的剩余3届哪些更新ITEMST反正

所以我的问题是: 怎么[1]发生,为什么它块U更新到表ITEMST

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

回答

4

您的查询返回的sql_id可能会或可能不会与实际获取该锁的查询相关。

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

+0

谢谢Justin,这很有道理。实际上,在锁定采样之前,我针对涉及ITEMST的任何SQL检查了会话669的ASH,但找不到任何SQL。难道说oracle只是没有对涉及实际获得锁的SQL的会话进行采样? – toddlermenot

+1

@toddlermenot - 当然,这完全有可能。 ASH只是从查询每秒顶部活动的会话开始。假设查询花费了不到一秒钟的时间,那么完全有可能它在初始样本中不会被捕获。取决于这是多大,ASH下采样数据时也可能会丢失。 –