Home  >  Article  >  Database  >  独立思考锁表了咋整

独立思考锁表了咋整

WBOY
WBOYOriginal
2016-06-07 16:13:191120browse

Session 1: scott@PRODselect * from dept1 where deptno=40 for update; Session 2: scott@PRODupdate dept1 set deptno=41 where deptno=40; 这时候session 2就被卡住了 首先你要知道为啥会卡住 可以通过v$session event列查看一下等待事件 那么就需要SI

Session 1:
scott@PROD>select * from dept1 where deptno=40 for update;

Session 2:
scott@PROD>update dept1 set deptno=41 where deptno=40;
这时候session 2就被卡住了

首先你要知道为啥会卡住

可以通过v$session event列查看一下等待事件

    那么就需要SID,可是Session 2卡住了啊,我没法直接在Session 2中查SID

        可以通过sql_id查出SID
<code class=" hljs vbnet">            sys@PROD>select sql_id,sql_text from v$sql where sql_text like 'update dept1%';

            SQL_ID        SQL_TEXT
            ------------- --------------------------------------------------
            8xxzy0hngvv6m update dept1 set deptno=41 where deptno=40
    有了SQL_ID好像不需要SID了啊…╮(╯▽╰)╭
<code class=" hljs cs">    sys@PROD>select sid,event,p1,p2 from v$session where sql_id='8xxzy0hngvv6m';

           SID EVENT                                                                    P1         P2
    ---------- ---------------------------------------------------------------- ---------- ----------
            44 enq: TX - row lock contention                                    1415053318     196621
现在知道原因了,原来是在等待TX锁,看来有人没commit啊

    那么我们现在就要查出是那个会话blocking了我们

    我的笨方法:

        在v$lock视图中有ID1,ID2这两列

            对于TM锁来说,ID1表示被锁定的对象的对象ID,ID2始终为0
            对于TX锁里说,ID1表示事物使用的回滚段编号以及在事物表中对应的记录编号,ID2表示该记录编号被重用的次数(wrapp)

        那么我们知道一个当执行DML操作时,会在表上加TM锁

            查一下dept1表的object_id
<code class=" hljs cs">                    sys@PROD>select object_id from dba_objects where object_name ='DEPT1';

                     OBJECT_ID
                    ----------
                         77723
            查出SID
<code class=" hljs cs">                    sys@PROD>select sid from v$lock where id1= 77723 ;

                           SID
                    ----------
                            44
                            46
<code class=" hljs brainfuck">                sys@PROD>select * from v$lock where sid in(44,46);

                ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
                ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
                00000000844D1F10 00000000844D1F68         46 AE        100          0          4          0       2870          0
                00000000844D21B0 00000000844D2208         44 AE        100          0          4          0       4472          0
                00000000844D2D28 00000000844D2D80         44 TX     196621       1408          0          6       2833          0
                00002B0B14D46228 00002B0B14D46288         44 TM      77723          0          3          0       2833          0
                00002B0B14D46228 00002B0B14D46288         46 TM      77723          0          3          0       2867          0
                00000000832749E8 0000000083274A60         46 TX     196621       1408          6          0       2841          1
            真相大白了
            44号会话(Session 2)需要获取TX锁,在他的REQUEST列值为6
            46号会话(Session 1)持有了TX锁,在他的LMODE列值为6 ,block列值为1表示它阻塞了别人获取LOMDE为6的锁

    把session 46 KILL了就好了,KILL之前记得问一下客户
<code class=" hljs sql">            Alter system kill session 'sid,serial#';
    简单的方法:

    得知等待事件是enq: TX – row lock contention,行锁,接下来就是要找到谁锁住了这个会话。在10gR2以后,只需要gv$session视图就可以迅速定位blocker,通过BLOCKING_INSTANCE和BLOCKING_SESSION字段即可。
<code class=" hljs brainfuck">            sys@PROD>select sid,inst_id,blocking_instance,blocking_session from gv$session where sid=44;

                   SID    INST_ID BLOCKING_INSTANCE BLOCKING_SESSION
            ---------- ---------- ----------------- ----------------
                    44          1                 1               46
关于TX锁的ID1和ID2

    对于TX锁里说,ID1表示事物使用的回滚段编号以及在事物表中对应的记录编号,ID2表示该记录编号被重用的次数(wrapp)

    可以从v$lock_type得到解释
<code class=" hljs vhdl">        SQL> SELECT ID1_TAG,ID2_TAG FROM V$LOCK_TYPE WHERE TYPE='TX';

        ID1_TAG         ID2_TAG
        --------------- ----------
        usn<<16 | slot  SEQUENCE
<code class=" hljs brainfuck">
        ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
        ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
        00000000844D1F10 00000000844D1F68         46 AE        100          0          4          0       2870          0
        00000000844D21B0 00000000844D2208         44 AE        100          0          4          0       4472          0
        00000000844D2D28 00000000844D2D80         44 TX     196621       1408          0          6       2833          0
        00002B0B14D46228 00002B0B14D46288         44 TM      77723          0          3          0       2833          0
        00002B0B14D46228 00002B0B【本文来自鸿网互联 (http://www.68idc.cn)】14D46288         46 TM      77723          0          3          0       2867          0
        00000000832749E8 0000000083274A60         46 TX     196621       1408          6          0       2841          1
<code class=" hljs vbnet">        sys@PROD>SELECT XIDUSN,XIDSLOT,XIDSQN FROM v$transaction WHERE addr='00000000832749E8';

            XIDUSN    XIDSLOT     XIDSQN
        ---------- ---------- ----------
                 3         13       1408
    XIDSQN和ID2很容易对上了

    ID1 和 XIDUSN、XIDSLOT怎么对呢


    将196621转换成16进制是0X3000D

    然后分高位和低位分别再转换为10进制,高位的16进制3就是十进制的3,也就是XIDUSN=3,而低位的16进制0D转换为10进制是13,也就是XIDSLOT=13。
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn