好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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、演示阻塞

?

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

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

--更新表,注,提示符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

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

?

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

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

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 阻塞(blocking blocked)介绍和实例演示的详细内容...

  阅读:30次