今天遇到一个sql,发生了大量的134的latch,134的latch是transaction allocation。数据库版本是9208.
该sql是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
SELECT DECODE(l.request, 0, 'Holder: ', 'Waiter: ') || l.sid sess, s.SQL_HASH_VALUE, l.id1, l.id2, l.lmode, l.request, l.type FROM V$LOCK l, v$session s WHERE (l.id1, l.id2, l.type) IN (SELECT id1, id2, type FROM V$LOCK WHERE request > 0) and l.SID = s.SID and exists (select sw.seq#, sw.sid || ',' || s.serial# sids, s.username, s.SQL_HASH_VALUE from v$session_wait sw, v$session s, dba_objects a where sw.sid = s.sid and sw.event in ('latch free', 'enqueue') and s.status = 'ACTIVE' and sw.STATE = 'WAITING' and s.username is not null and sw.seconds_in_wait > 30 and (a.object_id = s.row_wait_obj# or a.data_object_id = s.row_wait_obj#)) ORDER BY l.id1, l.request; |
据客户反映,这个sql之前没有出现问题,只是昨天做了修改,增加了对v$session表的关联。昨天的sql:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
SELECT DECODE(l.request, 0, 'Holder: ', 'Waiter: ') || l.sid sess, s.SQL_HASH_VALUE, l.id1, l.id2, l.lmode, l.request, l.type FROM V$LOCK l WHERE (l.id1, l.id2, l.type) IN (SELECT id1, id2, type FROM V$LOCK WHERE request > 0) and exists (select sw.seq#, sw.sid || ',' || s.serial# sids, s.username, s.SQL_HASH_VALUE from v$session_wait sw, v$session s, dba_objects a where sw.sid = s.sid and sw.event in ('latch free', 'enqueue') and s.status = 'ACTIVE' and sw.STATE = 'WAITING' and s.username is not null and sw.seconds_in_wait > 30 and (a.object_id = s.row_wait_obj# or a.data_object_id = s.row_wait_obj#)) ORDER BY l.id1, l.request; |
在查询相关文档后,引起这个问题的原因如下:
(1)频繁访问v$transaction视图会造成134的latch free(transaction allocation),可见Doc ID 42192.1 LATCH:TRANSACTION ALLOCATION
(2)v$transaction视图的基表是x$ktcxb,且v$lock视图的基表也是x$ktcxb,因此频繁访问v$lock也会造成134的latch free
(3)在sql改造之前,v$lock的查询只会执行一次,增加对v$session的关联之后,原来只访问一次的v$lock,变成了走nestloop循环访问v$lock,也就是频繁访问了x$ktcxb,因此造成134的latch
解决方案:
建一个global temporary table,将查询到的v$lock内容insert其中。或者直接用with as的写法。