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;
(0)

相关推荐

  • Oracle阻塞(blockingblocked)实例详解

    一.概述: 阻塞是DBA经常碰到的情形,尤其是不良的应用程序设计所造成的阻塞将导致数据库性能的严重下降,直至数据库崩溃.对DBA而言,有必要知道如何定位到当前系统有哪些阻塞,到底谁是阻塞者,谁是被阻塞者.本文对此给出了描述并做了相关演示. 二.演示阻塞: --更新表,注,提示符scott@CNMMBO表明用户为scott的session,用户名不同,session不同. scott@CNMMBO> update emp set sal=sal*1.1 where empno=7788; 1 ro

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

    阻塞是DBA经常碰到的情形,尤其是不良的应用程序设计的阻塞将导致性能严重下降直至数据库崩溃.对DBA而言,有必要知道如何定位到当前系统有哪些阻塞,到底谁是阻塞者,谁是被阻塞者.本文对此给出了描述并做了相关演示. 1.阻塞及其类型 a.什么是阻塞    一个会话持有某个资源的锁,而另一个会话在请求这个资源,就会出现阻塞(blocking).也就是说新的会话会被挂起,直到持有锁的会话放弃锁定的资源.大多数情况下,在一个交互式应用中被严重阻塞,即可表明应用逻辑有问题,这才是阻塞的根源. b.阻塞得类型

  • Oracle RAC环境下的阻塞(blocking blocked)介绍和实例演示

    RAC环境下的阻塞不同于单实例情形,因为我们需要考虑到位于不同实例的session.也就是说之前查询的v$session,v$lock相应的应变化为全局范围来查找.本文提供了2个查询脚本,并给出实例演示那些session为阻塞者,哪些为被阻塞者.有关阻塞的概念以及单实例环境下的阻塞请参考:Oracle 阻塞(blocking blocked) 1.演示环境 scott@DEVDB> select * from v$version where rownum<2; BANNER ---------

  • Oracle 分区索引介绍和实例演示

    分区索引(或索引分区)主要是针对分区表而言的.随着数据量的不断增长,普通的堆表需要转换到分区表,其索引呢,则对应的转换到分区索引.分区索引的好处是显而易见的.就是简单地把一个索引分成多个片断,在获取所需数据时,只需要访问更小的索引片断(块)即可实现.同时把分区放在不同的表空间可以提高分区的可用性和可靠性.本文主要描述了分区索引的相关特性并给出演示示例. 1.分区索引的相关概念 a.分区索引的几种方式:表被分区而索引未被分区:表未被分区,而索引被分区:表和索引都被分区 b.分区索引可以分为本地分区

  • MyBatis配置文件解析与MyBatis实例演示

    MyBatis介绍 MyBatis是一个持久层的ORM框架,使用简单,学习成本较低.可以执行自己手写的SQL语句,比较灵活.但是MyBatis的自动化程度不高,移植性也不高,有时从一个数据库迁移到另外一个数据库的时候需要自己修改配置,所以称只为半自动ORM框架 传统JDBC和Mybatis相比的弊病 传统JDBC @Test public void test() throws SQLException { Connection conn=null; PreparedStatement pstmt

  • Java 线程的生命周期详细介绍及实例代码

    当线程被创建并启动之后,它既不是一启动就进入执行状态,也不是一直处于执行状态,在其生命周期中,要经过"新建(New)"."就绪(Runnable)"."运行(Running')"."阻塞(Blocked)"和"死亡(Dead)"五种状态.线程在创建之后,不可能一直霸占着CPU独立运行,需要在多个线程之间切换,所以大部分时间处于运行.阻塞之间切换.  一.线程的状态 线程的存在有几种不同的状态,如下: New

  • Oracle生成单据编号存储过程的实例代码

    Oracle生成单据编号存储过程,在做订单类似的系统都可能会存在订单编号不重复,或是流水号按日,按年,按月进行重新编号. 可以参考以下存储过程 CREATE OR REPLACE procedure Pro_GetBillNO(TypeTable in varchar2,cur_mycursor out sys_refcursor) as DReceiptCode varchar2(40); DReceiptName varchar2(50); DPrefix1 varchar2(50); DI

  • oracle中merge into用法及实例解析

    merge into的形式: MERGE INTO [target-table] A USING [source-table sql] B ON([conditional expression] and [...]...) WHEN MATCHED THEN [UPDATE sql] WHEN NOT MATCHED THEN [INSERT sql] 作用:判断B表和A表是否满足ON中条件,如果满足则用B表去更新A表,如果不满足,则将B表数据插入A表但是有很多可选项,如下: 1.正常模式 2.

  • Spring请求参数校验功能实例演示

    SpringMVC支持的数据校验是JSR303的标准,通过在bean的属性上打上@NotNull.@Max等进行验证.JSR303提供有很多annotation接口,而SpringMVC对于这些验证是使用hibernate的实现,所以我们需要添加hibernate的一个validator包: 依赖引用 compile 'javax.validation:validation-api:2.0.0.Final' compile 'org.hibernate:hibernate-validator:6

  • java阻塞队列实现原理及实例解析

    这篇文章主要介绍了java阻塞队列实现原理及实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 阻塞队列与普通队列的不同在于.当队列是空的时候,从队列中获取元素的操作将会被阻塞,或者当队列满时,往队列里面添加元素将会被阻塞.试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素.同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完

  • Python While循环语句实例演示及原理解析

    这篇文章主要介绍了Python While循环语句实例演示及原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Python 编程中 while 语句用于循环执行程序,即在某条件下,循环执行某段程序,以处理需要重复处理的相同任务.其基本形式为: while 判断条件: 执行语句-- 执行语句可以是单个语句或语句块.判断条件可以是任何表达式,任何非零.或非空(null)的值均为true. 当判断条件假false时,循环结束. 执行流程图如下:

随机推荐