当前位置: 首页 > 编程笔记 >

Oracle 阻塞(blocking blocked)介绍和实例演示

孙泳
2023-03-14
本文向大家介绍Oracle 阻塞(blocking blocked)介绍和实例演示,包括了Oracle 阻塞(blocking blocked)介绍和实例演示的使用技巧和注意事项,需要的朋友参考一下

阻塞是DBA经常碰到的情形,尤其是不良的应用程序设计的阻塞将导致性能严重下降直至数据库崩溃。对DBA而言,有必要知道如何定位到当前系统有哪些阻塞,到底谁是阻塞者,谁是被阻塞者。本文对此给出了描述并做了相关演示。

1、阻塞及其类型

a、什么是阻塞
   一个会话持有某个资源的锁,而另一个会话在请求这个资源,就会出现阻塞(blocking)。也就是说新的会话会被挂起,直到持有锁的会话放弃锁定的资源。大多数情况下,在一个交互式应用中被严重阻塞,即可表明应用逻辑有问题,这才是阻塞的根源。
b、阻塞得类型
   数据库中有5条常见的DML语句可能会阻塞,即:INSERT、UPDATE、DELETE、MERGE 和SELECT FOR UPDATE。

2、几种不同类型阻塞的处理办法

a、INSERT阻塞主要是由于有一个带主键的表,或者表上有惟一的约束,在两个会话试图用同样的值插入一行时引发阻塞。多表通过引用完整性约束相互链接时,在其依赖的父表正在创建或删除期间,对子表的插入可能会阻塞。对于该类情形建议使用序列来生成主键/惟一列值。
b、对于UPDATE、DELETE、MERGE 和SELECT FOR UPDATE阻塞,只要有任一session使用这些操作已经锁定行,其余的必须处于等待状态。直到当前锁定行上的锁(排他锁)释放。对于该类情形,建议尽可能快速提交事务,或采用批量SQL方式提交。
c、对于一个阻塞的SELECT FOR UPDATE,解决方案很简单:只需增加NOWAIT 子句,它就不会阻塞了。

3、演示阻塞

--更新表,注,提示符scott@CNMMBO表明用户为scott的session,用户名不同,session不同。
scott@CNMMBO> update emp set sal=sal*1.1 where empno=7788;

1 row updated.

scott@CNMMBO> @my_env

SPID    SID SERIAL# USERNAME  PROGRAM
------------ ---------- ---------- --------------- ------------------------------------------------
11205    1073  4642 robin   oracle@SZDB (TNS V1-V3)

--另起两个session更新同样的行,这两个session都会处于等待,直到第一个session提交或回滚
leshami@CNMMBO> update scott.emp set sal=sal+100 where empno=7788;

goex_admin@CNMMBO> update scott.emp set sal=sal-50 where empno=7788;

--下面在第一个session 查询阻塞情况
scott@CNMMBO> @blocker 

BLOCK_MSG            BLOCK
-------------------------------------------------- ----------
pts/5 ('1073,4642') is blocking 1067,10438     1
pts/5 ('1073,4642') is blocking 1065,4464     1
--上面的结果表明session 1073,4642 阻塞了后面的2个
--即session 1073,4642是阻塞者,后面2个session是被阻塞者

--Author : Leshami
--Blog : http://blog.csdn.net/leshami

--下面查询正在阻塞的session id,SQL语句以及被阻塞的时间
scott@CNMMBO> @blocking_session_detail.sql

'SID='||A.SID||'WAITCLASS='||A.WAIT_CLASS||'TIME='||A.SECONDS_IN_WAIT||CHR(10)||'QUERY='||B.SQL_TEXT
-------------------------------------------------------------------------------------------------------
sid=1067 Wait Class=Application Time=5995
 Query=update scott.emp set sal=sal+100 where empno=7788

sid=1065 Wait Class=Application Time=225
 Query=update scott.emp set sal=sal-50 where empno=7788

--下面的查询阻塞时锁的持有情况 
scott@CNMMBO> @request_lock_type

USERNAME        SID TY LMODE  REQUEST   ID1  ID2
------------------------------ ---------- -- ----------- ----------- ---------- ----------
SCOTT        1073 TX Exclusive None   524319  27412
LESHAMI        1067 TX None  Exclusive  524319  27412
GOEX_ADMIN       1065 TX None  Exclusive  524319  27412
--可以看到LESHAMI,GOEX_ADMIN 2个用户都在请求524319/27412上的Exclusive锁,而此时已经被SCOTT加了Exclusive锁

--查询阻塞时锁的持有详细信息
scott@CNMMBO> @request_lock_detail

  SID USERNAME    OSUSER   TERMINAL     OBJECT_NAME   TY Lock Mode Req_Mode
---------- -------------------- --------------- ------------------------- -------------------- -- ----------- --------------------
  1065 GOEX_ADMIN   robin   pts/1      EMP     TM Row Excl
  1065 GOEX_ADMIN   robin   pts/1      Trans-524319   TX --Waiting-- Exclusive
  1067 LESHAMI    robin   pts/0      EMP     TM Row Excl
  1067 LESHAMI    robin   pts/0      Trans-524319   TX --Waiting-- Exclusive
  1073 SCOTT    robin   pts/5      EMP     TM Row Excl
  1073 SCOTT    robin   pts/5      Trans-524319   TX Exclusive 

文中涉及到的相关脚本如下:

robin@SZDB:~/dba_scripts/custom/sql> more my_env.sql 
SELECT spid, s.sid, s.serial#, p.username, p.program
FROM v$process p, v$session s
WHERE p.addr = s.paddr
  AND s.sid = (SELECT sid
     FROM v$mystat
     WHERE rownum = 1);

robin@SZDB:~/dba_scripts/custom/sql> more blocker.sql 
col block_msg format a50; 
select c.terminal||' ('''||a.sid||','||c.serial#||''') is blocking '||b.sid||','||d.serial# block_msg, a.block 
from v$lock a,v$lock b,v$session c,v$session d 
 where a.id1=b.id1 
 and a.id2=b.id2 
 and a.block>0
 and a.sid <>b.sid 
 and a.sid=c.sid 
 and b.sid=d.SID; 

robin@SZDB:~/dba_scripts/custom/sql> more blocking_session_detail.sql
--To find the query for blocking session

--Access Privileges: SELECT on v$session, v$sqlarea

SELECT  'sid='
   || a.SID
   || ' Wait Class='
   || a.wait_class
   || ' Time='
   || a.seconds_in_wait
   || CHR (10)
   || ' Query='
   || b.sql_text
 FROM v$session a, v$sqlarea b
 WHERE a.blocking_session IS NOT NULL AND a.sql_address = b.address
ORDER BY a.blocking_session
/
robin@SZDB:~/dba_scripts/custom/sql> more request_lock_type.sql
--This script generates a report of users waiting for locks.
--Access Privileges: SELECT on v$session, v$lock

SELECT sn.username, m.sid, m.type,
  DECODE(m.lmode, 0, 'None',
      1, 'Null',
      2, 'Row Share',
      3, 'Row Excl.',
      4, 'Share',
      5, 'S/Row Excl.',
      6, 'Exclusive',
    lmode, ltrim(to_char(lmode,'990'))) lmode,
  DECODE(m.request,0, 'None',
       1, 'Null',
       2, 'Row Share',
       3, 'Row Excl.',
       4, 'Share',
       5, 'S/Row Excl.',
       6, 'Exclusive',
       request, ltrim(to_char(m.request,
    '990'))) request, m.id1, m.id2
FROM v$session sn, v$lock m
WHERE (sn.sid = m.sid AND m.request != 0)
  OR (sn.sid = m.sid
    AND m.request = 0 AND lmode != 4
    AND (id1, id2) IN (SELECT s.id1, s.id2
  FROM v$lock s
      WHERE request != 0
    AND s.id1 = m.id1
        AND s.id2 = m.id2)
    )
ORDER BY id1, id2, m.request; 
robin@SZDB:~/dba_scripts/custom/sql> more request_lock_detail.sql
set linesize 190
col osuser format a15
col username format a20 wrap
col object_name format a20 wrap
col terminal format a25 wrap
col Req_Mode format a20
select B.SID, C.USERNAME, C.OSUSER, C.TERMINAL,
  DECODE(B.ID2, 0, A.OBJECT_NAME,
   'Trans-'||to_char(B.ID1)) OBJECT_NAME,
  B.TYPE,
  DECODE(B.LMODE,0,'--Waiting--',
      1,'Null',
      2,'Row Share',
      3,'Row Excl',
     4,'Share',
      5,'Sha Row Exc',
   6,'Exclusive',
      'Other') "Lock Mode",
  DECODE(B.REQUEST,0,' ',
      1,'Null',
      2,'Row Share',
      3,'Row Excl',
      4,'Share',
      5,'Sha Row Exc',
      6,'Exclusive',
      'Other') "Req_Mode"
 from DBA_OBJECTS A, V$LOCK B, V$SESSION C
where A.OBJECT_ID(+) = B.ID1
 and B.SID = C.SID
 and C.USERNAME is not null
order by B.SID, B.ID2;
 类似资料:
  • 本文向大家介绍Oracle阻塞(blockingblocked)实例详解,包括了Oracle阻塞(blockingblocked)实例详解的使用技巧和注意事项,需要的朋友参考一下 一、概述: 阻塞是DBA经常碰到的情形,尤其是不良的应用程序设计所造成的阻塞将导致数据库性能的严重下降,直至数据库崩溃。对DBA而言,有必要知道如何定位到当前系统有哪些阻塞,到底谁是阻塞者,谁是被阻塞者。本文对此给出了描

  • 本文向大家介绍Oracle RAC环境下的阻塞(blocking blocked)介绍和实例演示,包括了Oracle RAC环境下的阻塞(blocking blocked)介绍和实例演示的使用技巧和注意事项,需要的朋友参考一下 RAC环境下的阻塞不同于单实例情形,因为我们需要考虑到位于不同实例的session。也就是说之前查询的v$session,v$lock相应的应变化为全局范围来查找。本文提供

  • 本文向大家介绍Oracle 分区索引介绍和实例演示,包括了Oracle 分区索引介绍和实例演示的使用技巧和注意事项,需要的朋友参考一下 分区索引(或索引分区)主要是针对分区表而言的。随着数据量的不断增长,普通的堆表需要转换到分区表,其索引呢,则对应的转换到分区索引。分区索引的好处是显而易见的。就是简单地把一个索引分成多个片断,在获取所需数据时,只需要访问更小的索引片断(块)即可实现。同时把分区放在

  • 本文向大家介绍简单介绍PHP非阻塞模式,包括了简单介绍PHP非阻塞模式的使用技巧和注意事项,需要的朋友参考一下 非阻塞模式是指利用socket事件的消息机制,Server端与Client端之间的通信处于异步状态。 让PHP不再阻塞当PHP作为后端处理需要完成一些长时间处理,为了快速响应页面请求,不作结果返回判断的情况下,可以有如下措施: 一、若你使用的是FastCGI模式,使用fastcgi_fi

  • 假设我们有: 线程1,包含actor A、B和C。 包含执行元y的线程2。 包含演员Z的线程3。 演员A和B正在监听演员Y的消息。 然后,参与者C向参与者Z发出阻塞请求。 我包含了Actor Y,以允许它在Z处理来自C的请求时发送消息。 所有线程都在不同的物理核心上--它们并行运行。

  • 本文向大家介绍Java中的阻塞队列详细介绍,包括了Java中的阻塞队列详细介绍的使用技巧和注意事项,需要的朋友参考一下 Java中的阻塞队列 1. 什么是阻塞队列? 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是: 在队列为空时,获取元素的线程会等待队列变为非空。 当队列满时,存储元素的线程会等待队列可用。 阻塞队列常用于生产者和消费者的场景,生产者是往队列