当前位置: 首页 > BACKUP & RESTORE > 正文

       最近客户遇到了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还回结果后,KILLfor 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进程在回退的时候同样会获取TX6级别的锁,所以就导致出现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$

上面查看到死事务的XIDUNDO段的名字,下面通过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