【问题标题】:Oracle SQL - SELECT query locks index & blocks DML sessionsOracle SQL - SELECT 查询锁定索引并阻止 DML 会话
【发布时间】:2017-04-25 06:34:18
【问题描述】:

我们在生产中发生了一些非常奇怪的锁定。我们设置了一个 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;

我们今天收到了锁警报:

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

所以从上面我们可以观察到 session 669 的 sqlid fbnhs4gd9a7yn 已经锁定了索引 IDX_005 并阻塞了其余的会话。

现在最奇怪的部分:

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

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

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

【问题讨论】:

    标签: sql oracle plsql concurrency oracle11g


    【解决方案1】:

    您的查询返回的sql_id 可能与实际获取锁的查询相关,也可能不相关。

    例如,在 SID 669 中,如果我更新 ITEMST,然后运行查询,但我没有提交我的 update,你会看到 669 正在运行 SELECT 语句并且它包含一个锁。会话实际获得锁的是较早的UPDATE(或INSERT 或其他)。只是没有一种简单的方法可以查看会话之前执行的哪些查询获得了其他会话现在正在等待的锁。

    【讨论】:

    • 谢谢贾斯汀,这是有道理的。实际上,在对锁定进行采样之前,我检查了会话 669 的 ASH 是否有任何涉及 ITEMST 的 SQL,但我找不到任何 SQL。会不会是 oracle 没有对涉及实际获取锁的 SQL 的会话进行采样?
    • @toddlermenot - 这完全有可能,当然。 ASH 刚开始时会查询在每秒顶部处于活动状态的会话。假设进行查看的查询运行时间不到一秒钟,那么它完全有可能不会在初始样本中被捕获。根据它的年龄,它也可能在 ASH 对数据进行下采样时丢失。
    猜你喜欢
    • 1970-01-01
    • 2021-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多