如何解决等待事件 ‘enqueue’?
如何解决等待事件 ‘enqueue’?
产生原因:
Enqueues是在读取各种不同的数据库资源时在其上产生的锁,该等待意味着在访问同样的数据库资源时需要等待其他会话已经获取的锁。
诊断方法:
在会话级,查询视图V$SESSION_WAIT时如果有该事件存在,那么该视图中的
P1-表示锁类型和模式。
P2-锁ID1,以十进制表示的enqueue名称的ID1
P3-锁ID2,以十进制表示的enqueue名称的ID2
实际的等待时间依赖于锁的类型,在等待超时后数据库会检查已获取锁的会话,如果会话仍然存活那么其他会话会继续等待。
通过查询视图V$LOCK可以获取锁的相关信息,其中TYPE列表示锁类型,ID1表示锁的ID1,ID2表示锁的ID2:
SELECT TYPE,ID1,ID2,DECODE(request,0,'Holder: ','Waiter: ')||sid session
FROM V$LOCK
WHERE (id1, id2, type) IN
(SELECT id1, id2, type FROM V$LOCK WHERE request>0)
ORDER BY id1, request;
在实例级,通过查询视图V$SYSSTAT中的enqueue waits统计信息和Statspack中的Statistics部分可以诊断该事件实际上发生的等待次数。通过查询视图V$ENQUEUE_STAT可以诊断那些enqueues导致了等待:
SELECT eq_type "Lock",
total_req# "Gets",
total_wait# "Waits",
cum_wait_time
FROM V$enqueue_stat
WHERE Total_wait# > 0;
通常的解决方法:
基于不同的锁类型有不同的解决方法。经常发生的等待类型为:
TX Transaction Lock:通常是由于应用的原因造成锁等待。
TM DML enqueue:通常是由于应用原因,部分是因为在外键约束上没有建立索引而导致。
ST Space Management Enqueue:通常是由于过多的空间管理(比如因为extent过小而导致extent的频繁分配/大量的排序而导致临时段的分配)而产生。