阻塞是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实例提示blocked,Oracle 阻塞(blocking blocked)介绍和实例演示相关推荐

  1. oracle全局索引 前缀索引_Oracle 分区索引介绍和实例演示

    --环境 SQL> select * from v$version where rownum<2; BANNER ------------------------------------- ...

  2. C# 解决连接Oracle数据库提示“需要Oracle客户端软件version8.1.7或更高版本”的问题

    由于不能更改服务器上Oracle数据库的权限所以采用下面这个方法. 首先下载"instantclient_11_2" 百度云连接 链接:https://pan.baidu.com/ ...

  3. oracle+查询主机地址,oracle函数:获取Internet主机名和ip地址

    您可能感兴趣的话题: Oracle 核心提示:oracle函数获取Internet主机名和ip地址 Oracle包utl_inaddr 作用:用于取得局域网或Internet环境中的主机名和IP地址. ...

  4. oracle几种例外,Oracle例外用法实例详解

    本文实例讲述了Oracle例外用法.分享给大家供大家参考,具体如下: 一.例外分类 oracle将例外分为预定义例外.非预定义例外和自定义例外三种. 1).预定义例外用于处理常见的oracle错误. ...

  5. oracle如何写check,Oracle之Check约束实例详解

    Oracle | PL/SQL Check约束用法详解 1. 目标 实例讲解在Oracle中如何使用CHECK约束(创建.启用.禁用和删除) 2. 什么是Check约束? CHECK约束指在表的列中增 ...

  6. Oracle数据库名与Oracle实例名的关系

    1 数据库名 1.1 数据库名的概念 数据库名(db_name)就是一个数据库的标识,就像人的身份证号一样.如果一台机器上装了多个数据库,那么每一个数据库都有一个数据库名.在数据库安装或创建完成之后, ...

  7. Navicat Premium 12连接Oracle时提示oracle library is not loaded的问题解决

    Navicat Premium 12连接Oracle时提示oracle library is not loaded的问题解决 参考文章: (1)Navicat Premium 12连接Oracle时提 ...

  8. oracle存储过程循环单列,Oracle存储过程循环语法实例分析

    本文实例讲述了Oracle存储过程循环语法.分享给大家供大家参考,具体如下: 1.简单循环 语法 sql;"> loop statements; end loop; 例子: sql;& ...

  9. Oracle使用ini启动,python操作ini类型配置文件的实例教程

    一.ini文件介绍 INI文件格式是某些平台或软件上的配置文件的非正式标准,以节(section)和键(key)构成,常用于微软Windows操作系统中.这种配置文件的文件扩展名多为INI 二.ini ...

最新文章

  1. html显示隐藏密码,Web前端,登录密码显示隐藏眼睛
  2. LiveVideoStack线上交流分享 ( 七) —— 舞台现场直播技术实践
  3. web程序入门五(http无状态)
  4. 作者:刘昂(1990-),男,中国科学院计算机网络信息中心工程师
  5. Subsequence Count (线段树)
  6. SLAM_轨迹算法精度评价指标(ATE、RPE)
  7. 快速学习django
  8. 使用mysql 函数 IFNULL 解决某些字段为null
  9. grid 安装失败 卸载grid 实操
  10. SnowNLP简易教程:分词、词性标注、情感分析、繁体转换、关键字抽取、相似度计算
  11. windows操作系统下新建txt文件快捷键
  12. MES系统的工艺管理与绩效管理
  13. Eureka 源码解析 —— Eureka-Server 集群同步
  14. 8086 CPU 内部结构
  15. 数字人民币应用日渐成熟,领先美欧至少5年
  16. Reading Comprehension必读paper汇总
  17. express+socket.io 共享session
  18. centos7 串口配置修改_Linux串口参数设置
  19. 激光雷达的性能指标-以大疆livox-Mid40激光雷达为例
  20. 温度自动控制系统matlab,某温度控制系统的MATLAB仿真

热门文章

  1. 函数的连续和可导的关系
  2. STM32学习笔记 第二章 STM32资源介绍
  3. 1265: [蓝桥杯2015决赛]四阶幻方
  4. 解密安卓微信聊天记录
  5. 简易jQuery轮播图插件
  6. 自主可控计算机扯的重要性,2019自主可控计算机大会在京召开
  7. 如何在雷电模拟器里使用YiLu代理的动态ip?
  8. Linux中ps配合Kill进程的N种方法
  9. Coding创建项目,并用git把本地上传到Coding
  10. 百度再出Lens黑科技!用Paddle Mobile实现类人眼视觉AI能力