当前位置: 首页 > 备份与恢复 > 正文

       最近客户遇到了for update回退导致业务阻塞的情况,下面是在自己的环境中模拟for update死事务的回退及回退过程中占用的行锁与是否影响其它的dml语句。

1 环境介绍

www.htz.pw > select * from v$version where rownum=1;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

www.htz.pw > !uname -a
Linux orcl9i 2.6.9-89.EL #1 Mon Apr 20 10:22:29 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

2 创建测试表

这里使用dba_objects视图来创建测试表,并大量插入数据

CREATE TABLE htz.htz
(
   ID               NUMBER,
   OWNER            VARCHAR2 (30),
   OBJECT_NAME      VARCHAR2 (128),
   SUBOBJECT_NAME   VARCHAR2 (30),
   OBJECT_ID        NUMBER,
   DATA_OBJECT_ID   NUMBER,
   OBJECT_TYPE      VARCHAR2 (30),
   CREATED          DATE,
   LAST_DDL_TIME    DATE,
   TIMESTAMP        VARCHAR2 (30),
   STATUS           VARCHAR2 (30),
   TEMPORARY        VARCHAR2 (30),
   GENERATED        VARCHAR2 (30),
   SECONDARY        VARCHAR2 (30),
   NAMESPACE        VARCHAR2 (30),
   EDITION_NAME     VARCHAR2 (30)
)
www.cdhtz.com > alter system set "_disable_logging"=true scope=spfile;
System altered.
www.cdhtz.com > startup force;
/* Formatted on 2014/11/13 13:38:39 (QP5 v5.240.12305.39446) */
BEGIN
   FOR i IN 1 .. 2000
   LOOP
      INSERT INTO htz.htz
         SELECT htz.htz_sequence.NEXTVAL,
                OWNER,
                OBJECT_NAME,
                SUBOBJECT_NAME,
                OBJECT_ID,
                DATA_OBJECT_ID,
                OBJECT_TYPE,
                CREATED,
                LAST_DDL_TIME,
                TIMESTAMP,
                STATUS,
                TEMPORARY,
                GENERATED,
                SECONDARY,
                NAMESPACE,
                EDITION_NAME
           FROM dba_objects;
      COMMIT;
   END LOOP;
END;
/
表的大小为18G,有点大哦。
www.cdhtz.com >  select segment_name,bytes/1024/1024/1024 from dba_segments where owner='HTZ' and segment_name='HTZ';

SEGMENT_NA BYTES/1024/1024/1024
---------- --------------------
HTZ                  18.7705078
www.cdhtz.com > alter database tempfile 1 autoextend on maxsize 31g;
www.cdhtz.com > alter database datafile 4 autoextend on maxsize 31g;

3 kill for update进程

www.cdhtz.com > select /*+ parallel(a 4) */ * from htz.htz a where mod(id,2)=0 for update;
等SQL还回结果后,KILL掉for update的进程,事务等待smon进程来回退。

4 现象分析

4.1 smon持有锁情况

www.cdhtz.com > oradebug setospid 13491
Oracle pid: 13, Unix process pid: 13491, image: oracle@orcl9i (SMON)
www.cdhtz.com > oradebug tracefile_name;
/oracle/app/oracle/diag/rdbms/orcl1123/orcl1123/trace/orcl1123_smon_13491.trc
www.cdhtz.com > oradebug event 10704 trace name context forever,level 12;
Statement processed.
在trace文件中,可以看到下面的信息,这里可以看到很多TX级别的锁,模式都为6,但是在整个TRACE文件中,并找到在对象HTZ上面的任何TM级别的锁,说明SMON在事务回退过程中,只占用行级别的锁,不占用TM级别的锁,但是正常情况下获取TX级别的锁之前必须获取TM级别的锁。另外为什么说这么的TX级别说就是之前的for update语句占用的TX锁,这个问题会在另外说明的。
*** 2014-11-14 10:27:08.161
ksqcmi: TX,100020,ad mode=6 timeout=0
ksqcmi: returns 51
ksqgtl: RETURNS 51

*** 2014-11-14 10:27:08.161
ksqgtl *** TX-00100020-000000ad mode=6 flags=0x10001 timeout=0 ***
ksqgtl: no transaction
ksqgtl: use existing ksusetxn DID
ksqgtl:
        ksqlkdid: 0001-000D-00000002

*** 2014-11-14 10:27:08.161
*** ksudidTrace: ksqgtl
        ksusesdi:   0001-000D-00000003
        ksusetxn:   0001-000D-00000002

*** 2014-11-14 10:27:08.161
ksqcmi: TX,100020,ad mode=6 timeout=0
ksqcmi: returns 51
ksqgtl: RETURNS 51

*** 2014-11-14 10:27:08.161
ksqgtl *** TX-00100020-000000ad mode=6 flags=0x10001 timeout=0 ***
ksqgtl: no transaction
ksqgtl: use existing ksusetxn DID
ksqgtl:
        ksqlkdid: 0001-000D-00000002

*** 2014-11-14 10:27:08.161
*** ksudidTrace: ksqgtl
        ksusesdi:   0001-000D-00000003
        ksusetxn:   0001-000D-00000002

*** 2014-11-14 10:27:08.161
ksqcmi: TX,100020,ad mode=6 timeout=0
ksqcmi: returns 51
ksqgtl: RETURNS 51

4.2 是否阻塞其它的DML语句

www.cdhtz.com > update htz.htz set owner='HTZ' where id=2;
1 row updated.
www.cdhtz.com > update htz.htz set owner='HTZ' where id=4;
1 row updated.
www.cdhtz.com > rollback;
Rollback complete.
www.cdhtz.com > update htz.htz set owner='HTZ' where id=82163330;
1 row updated.
这里看到单行的DML语句是没有受到影响的
www.cdhtz.com > update htz.htz set owner='HTZ' where   mod(id,2)=0;
HANG住了,为什么这里HANG住了呢?这里我们可以查询到update处理的行号是一直在变化的,整个进程不是被真的HANG住了,而是执行相当的慢的,因为update在更新行的时候会获取TX6级别的锁,而SMON进程在回退的时候同样会获取TX为6级别的锁,所以就导致出现TX级别的等待。
所以通过DML测试可以看到SMON在回退死事务的时候是不会阻塞其它的DML事务,除非SMON回退行时,持有正在回退行的TX 6级别的锁,如果此时事务要修改此行,就会出现TX等待,但是很快就应该消失。

4.3 查询死事务回退的对象与SQL语句

由于事务在v$transaction里面已经没有记录,所以不可能通过v$transaction查询死事务信息与被KILL SESSION的信息包括SQLID信息

新开一个会话,并记录下会话的SPID
www.cdhtz.com > @tran_dead.sql
KTUXECFL                   COUNT(*)
------------------------ ----------
DEAD                              2
NONE                            470
ADDR               KTUXEUSN   KTUXESLT   KTUXESQN   KTUXESIZ
---------------- ---------- ---------- ---------- ----------
0000002A97FC5278         15          4        135          0
0000002A97FC5C18         16         32        173     556643
www.cdhtz.com > select * from v$rollname where usn=16;

       USN NAME
---------- ------------------------------
        16 _SYSSMU16$
上面查看到死事务的XID与UNDO段的名字,下面通过dump undo段的信息,这里注意到xid的信息可以跟前面提到 SMON持有的tx锁的ID1相关联。ID1就是由ktuxeusn,ktuxeslt两部分组成,可以通过下面SQL来转换
select trunc(id1 / 65536) usn, mod(id1 / 65536) slot, id2 wrap, Imode
  from v$lock
 where type = 'TX';

www.cdhtz.com > Alter system dump undo block ‘_SYSSMU16$’ xid 16 32 173;      

dump文件中我们可以看到如下的信息,这里可以看到对象的object_id表空间信息。   

*—————————–

* Rec #0x1c  slt: 0x20  objn: 82523(0x0001425b)  objd: 82523  tblspc: 9(0x00000009)

*       Layer:  11 (Row)   opc: 1   rci 0x1b

Undo type:  Regular undo   Last buffer split:  No

Temp Object:  No

Tablespace Undo:  No

rdba: 0x00000000

*—————————–

KDO undo record:

KTB Redo

op: 0x02  ver: 0x01

compat bit: 4 (post-11) padding: 1

op: C  uba: 0x01081e1b.03dc.1b

KDO Op code: LKR row dependencies Disabled

  xtype: XA flags: 0x00000000  bdba: 0x00db3d2b  hdba: 0x00c01d9a

itli: 2  ispac: 0  maxfr: 4858

tabn: 0 slot: 69 to:

根据对象号就可以找到对象的信息了

www.cdhtz.com > @object_by_id.sql

Enter Search Object Id (i.e. 1235) : 82523

OWNER                OBJECT_NAME

——————– ————

HTZ                  HTZ

查看被KILL会话的信息与SQL的信息,这里可以通过ASH的信息来查询

由于记录丢失,这里就不写了,在v$active_session_history中,可以通过下面几个段对定位,下面几个值都可以在dumpundo块中找到,上面默认的部分标注了下面的几个值,具体可以见:undo块的rowid

CURRENT_OBJ#        

CURRENT_FILE#

CURRENT_BLOCK#

CURRENT_ROW#

4.4 计算死事务回退时间

www.cdhtz.com > @tran_dead.sql

KTUXECFL                   COUNT(*)
------------------------ ----------
DEAD                              4
NONE                            468

ADDR               KTUXEUSN   KTUXESLT   KTUXESQN   KTUXESIZ
---------------- ---------- ---------- ---------- ----------
0000002A97FE77C8         15          4        135          0
0000002A97FE7EA8         17         24        128          0
0000002A97FE8060         21         29        119     627341
0000002A97FE76C0         24          1        131          0
DO YOU COMPUTE RECOVERY TIME :DO ENTER ,NOT CTRL+C: 21
Enter Search Usn (i.e. 3) : 21
Enter Search Slt (i.e. 4) : 29
time cost Hours:1.34(单位小时)

测试FOR UPDATE事务的回退:等您坐沙发呢!

发表评论

gravatar

? razz sad evil ! smile oops grin eek shock ??? cool lol mad twisted roll wink idea arrow neutral cry mrgreen

快捷键:Ctrl+Enter