模拟enq: TX – allocate ITL entry以及数据块dump文件分析


ITL的含义

ITL,即Interested Transaction List,也就是事务槽,是一种数据块的内部结构,它位于数据块头中。当对数据块做修改的时候,进程需要获取一个空的事务槽。ITL事物槽由槽位号、XIDUbaFlagLckScn/Fsc组成。ITL的个数是由参数initrans控制,maxtrans参数已经被废弃。默认initrans值是1,但是实际上此时ITL槽个数是2.当大量并发的update语句发生时,可能会因为槽位不够分配而出现等待事件enq: TX - allocate ITL entry

可能会有人疑问,默认是2个槽位的话,对oltp的系统而言岂不是很容易就发生这个等待事件,其实不是这样的。ITL槽也是需要空间的,这2个只是预分配,只要数据块还有空间,就可以再次分配,直到数据块上没有空间分配了。而且ITL槽是可循环使用的,只要事物提交了就可以再次重用。说到这里就想到了pctfree参数了,默认是10%空余空间,这部分空间是可以用来分配事务槽的。

 

 

模拟enq: TX – allocate ITL entry等待

创建测试表:

SQL> create table test (a number,b varchar2(2000)) initrans 1 pctfree 0;

Table created.

 

插入数据:

SQL> insert into test select object_id,lpad(object_name,2000,'x') from dba_objects where rownum<50;

SQL> commit;

Commit complete.

SQL> select distinct dbms_rowid.rowid_relative_fno(rowid) file#,

  2         dbms_rowid.rowid_block_number(rowid) block# from test ;

 

 

     FILE#     BLOCK#

---------- ----------

         7       1295

         7       1289

        12       2411

         7       1291

        12       2422

        12       2414

         7       1294

        12       2413

        12       2412

        12       2415

         7       1292

 

     FILE#     BLOCK#

---------- ----------

         7       1288

         7       1290

         7       1293

 

14 rows selected.

 

[oracle@oggtest1 ~]$ more bbed.par

blocksize=8192

listfile=/home/oracle/filelist.txt

mode=edit

[oracle@oggtest1 ~]$ more filelist.txt

7 /tpdata/oradata/ogg1/test01.dbf

12 /tpdata/oradata/ogg1/test02.dbf

 

 

BBED> set file  7 block 1290

        FILE#           7

        BLOCK#          1290

 

BBED> map

 File: /tpdata/oradata/ogg1/test01.dbf (7)

 Block: 1290                                  Dba:0x01c0050a

------------------------------------------------------------

 KTB Data Block (Table/Cluster)

 

 struct kcbh, 20 bytes                      @0      

 

 struct ktbbh, 72 bytes                     @20     

 

 struct kdbh, 14 bytes                      @100    

 

 struct kdbt[1], 4 bytes                    @114    

 

 sb2 kdbr[4]                                @118    

 

 ub1 freespace[26]                          @126     

 

 ub1 rowdata[8036]                          @152    

 

 ub4 tailchk                                @8188   

 

 

BBED> p ktbbh

struct ktbbh, 72 bytes                      @20     

   ub1 ktbbhtyp                             @20       0x01 (KDDBTDATA)

   union ktbbhsid, 4 bytes                  @24     

      ub4 ktbbhsg1                          @24       0x000130e7

      ub4 ktbbhod1                          @24       0x000130e7

   struct ktbbhcsc, 8 bytes                 @28     

      ub4 kscnbas                           @28       0x009eeb6f

      ub2 kscnwrp                           @32       0x0000

   sb2 ktbbhict                             @36       7938

   ub1 ktbbhflg                             @38       0x32 (NONE)

   ub1 ktbbhfsl                             @39       0x01

   ub4 ktbbhfnx                             @40       0x03000968

   struct ktbbhitl[0], 24 bytes             @44     

      struct ktbitxid, 8 bytes              @44     

         ub2 kxidusn                        @44       0x0003

         ub2 kxidslt                        @46       0x0004

         ub4 kxidsqn                        @48       0x00005560

      struct ktbituba, 8 bytes              @52     

         ub4 kubadba                        @52       0x00c00695

         ub2 kubaseq                        @56       0x0370

         ub1 kubarec                        @58       0x12

      ub2 ktbitflg                          @60       0x2004 (KTBFUPB)

      union _ktbitun, 2 bytes               @62     

         sb2 _ktbitfsc                      @62       0

         ub2 _ktbitwrp                      @62       0x0000

      ub4 ktbitbas                          @64       0x009eeb73

   struct ktbbhitl[1], 24 bytes             @68     

      struct ktbitxid, 8 bytes              @68     

         ub2 kxidusn                        @68       0x0000

         ub2 kxidslt                        @70       0x0000

         ub4 kxidsqn                        @72       0x00000000

      struct ktbituba, 8 bytes              @76     

         ub4 kubadba                        @76       0x00000000

         ub2 kubaseq                        @80       0x0000

         ub1 kubarec                        @82       0x00

      ub2 ktbitflg                          @84       0x0000 (NONE)

      union _ktbitun, 2 bytes               @86     

         sb2 _ktbitfsc                      @86       0

         ub2 _ktbitwrp                      @86       0x0000

      ub4 ktbitbas                          @88       0x00000000

ub1 freespace[26] :表明这个块上还剩下26bytes

struct ktbbhitl[0], 24 bytesstruct ktbbhitl[1], 24 bytes代表两个itl槽,因为创建表时指定initrans1,一个itl槽大小为24bytes

所以,这个数据块上最多只能承受三个事物,2个事物可以用现成的itl槽,还可以从块的空闲空间中分配第三个槽位,但是分配完之后块只剩2bytes,不够分配第四个槽位,所以当第四个事物来临时,就会发生enq: TX - allocate ITL entry等待事件。

SQL> select a

  2  from (select a, dbms_rowid.rowid_block_number(rowid) block# from test)

  3  where block# = 1290 and rownum<=5;

 

         A

----------

        52

        30

        18

        50

 

session1:

update test set b=b where a=52;

session2:

update test set b=b where a=30;

session3:

update test set b=b where a=18;

session4:

update test set b=b where a=50;

 

此时出现enq: TX - allocate ITL entry等待事件:

\n=============Wed Jun 27 04:42:49 CST 2018===================\n

 

   INST_ID     EVENT# EVENT                             COUNT(*)

---------- ---------- ------------------------------- ----------

         1        341 SQL*Net message to client                1

         1        238 enq: TX - allocate ITL entry             1

此时将第一个事物提交,第四个事物修改成功:

SQL> update test set b=b where a=50;

 

1 row updated.

Itl槽被重用了。

等待事件也消失了:

\n=============Wed Jun 27 05:02:01 CST 2018===================\n

 

   INST_ID     EVENT# EVENT                             COUNT(*)

---------- ---------- ------------------------------- ----------

         1        341 SQL*Net message to client                1

 

 

 

数据块dump文件解读

Dumpfile  7 block 1290数据块:

SQL> oradebug setmypid

Statement processed.

SQL> alter system dump datafile 7 block 1290;

 

System altered.

 

SQL> oradebug tracefile_name

/tpsys/app/oracle/diag/rdbms/ogg1/ogg1/trace/ogg1_ora_22110.trc

 

Start dump data blocks tsn: 8 file#:7 minblk 1290 maxblk 1290

Block dump from cache:

Dump of buffer cache at level 4 for tsn=8, rdba=29361418

BH (0x8df761c8) file#: 7 rdba: 0x01c0050a (7/1290) class: 1 ba: 0x8d1b4000

  set: 3 pool 3 bsz: 8192 bsi: 0 sflg: 2 pwc: 1121,28

  dbwrid: 0 obj: 78055 objn: 78055 tsn: 8 afn: 7 hint: f

  hash: [0x85f66918,0xa7f5f768] lru: [0x85f66950,0x8dfb3b20]

  ckptq: [NULL] fileq: [NULL] objq: [NULL]

  st: CR md: NULL tch: 1

  cr: [scn: 0x0.9eee55],[xid: 0x9.1e.556e],[uba: 0xc08d9d.392.b],[cls: 0x0.9eee55],[sfl: 0x1],[lc: 0x0.9eee55]

  flags: only_sequential_access

  cr pin refcnt: 0 sh pin refcnt: 0

tsn:tablespace number,tsn:8代表表空间号为8的表空间。

SQL>  select ts#,NAME from v$tablespace where ts#=8;

 

       TS# NAME

---------- ------------------------------

         8 TEST

 

 

File#7是指文件号为7的数据文件:

SQL> select file_id,FILE_NAME,TABLESPACE_NAME from dba_data_files where file_id=7;

   FILE_ID    FILE_NAME                               TABLESPACE_NAME

---------- -------------------------------------------------- ------------

         7 /tpdata/oradata/ogg1/test01.dbf                    TEST

minblk 1290 maxblk 1290是指dump的数据块的范围。

 

 

rdba=29361418rdba: 0x01c0050a (7/1290)

rdba就是相对数据块的位置,一个是10进制,一个是16进制。含义是7号数据文件的1290号块。

SQL> select to_number('1c0050a','xxxxxxxxxxxxxxxxxx') from dual;

 

TO_NUMBER('1C0050A','XXXXXXXXXXXXXXXXXX')

-----------------------------------------

                                 29361418

class: 1:表示块的类型。1代表数据块。对应x$bh.class

ba: 0x8d1b4000block address。指块在buffer cache中的内存地址,即x$bh.ba

 

 

set: 3x$bh.state3代表一致性读。

bsz: 8192block size 8k

dbwrid: 0 obj: 78055 objn: 78055 tsn: 8 afn: 7

dbwnn0Objx$bh.obj,是指数据所在对象的idObjnobject name id

tsn上面有,afn,绝对数据文件号。

 

 

hash: [0x85f66918,0xa7f5f768]

哈希链表后面和前面的位置。哈希链表是双向的,即x$bh.nxt_hash x$bh.prv_hash

 

lru: [0x85f66950,0x8dfb3b20]

lru链表后面和前面的位置。这条链也是双向的,即x$bh.nxt_repl x$bh.prv_repl

 

st: CR一致性读。

tch: 1。访问次数为1

ckptq: [NULL]

检查点队列哈希值

 

fileq: [NULL]

文件队列哈希值

 

cr: [scn: 0x0.9eee55],[xid: 0x9.1e.556e],[uba: 0xc08d9d.392.b],[cls: 0x0.9eee55],[sfl: 0x1],[lc: 0x0.9eee55]

产生此cr块时的scn

Xid事务id,因为此事务产生了一致性读。

Uba:回滚段地址。undo文件号和数据块号+回滚序列号+回滚记录号 

 

 

flags: only_sequential_access。对应x$bh. FLAG

 

 

 

 

Block header dump:  0x01c0050a

 Object id on Block? Y

 seg/obj: 0x130e7  csc: 0x00.9f5691  itc: 3  flg: E  typ: 1 - DATA

     brn: 1  bdba: 0x3000968 ver: 0x01 opc: 0

     inc: 0  exflg: 0

 

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0009.01e.0000556e  0x00c08d9d.0392.0b  ----    1  fsc 0x0000.00000000

0x02   0x0007.013.000054a6  0x00c0093c.02d6.08  ----    1  fsc 0x0000.00000000

0x03   0x0006.009.0000554a  0x00c034be.025a.0c  ----    1  fsc 0x0000.00000000

 

seg/obj:块所在事物object id

Csc:最后一次块清除时候的scn

Itc:就是itl个数,这里是3,跟下面槽个数一致

Typ:数据块类型,1代表数据块,2代表索引块。

Xid:事务idXid组成:Undo Segment Number +Transaction Table Slot Number+ Wrap

 0x0009.01e.0000556e9.30. 21870
Uba:事务的回滚段地址。Uba组成: undo文件号和数据块号+回滚序列号+回滚记录号

0x00c08d9d.0392.0b12619165. 914.11

Flag:事务标志位,各个标志的含义分别是:
C = transaction has been committed and locks cleaned out  

B = this undo record contains the undo for this ITL entry
U = transaction committed (maybe long ago); SCN is an upper bound 

T  = transaction was still active at block cleanout SCN  

Lck:事务所影响的行数。因为都只更新了一行,所以值都是1.
Scn/FscCommit SCN或者快速提交(Fast Commit Fsc)的SCN。因为事务都没有提交,所以显示为0

 

 

bdba: 0x01c0050a

data_block_dump,data header at 0x7fc2e8ab9a7c

===============

tsiz: 0x1f80  

hsiz: 0x1a

pbl: 0x7fc2e8ab9a7c

     76543210

flag=--------

ntab=1

nrow=4

frre=-1

fsbo=0x1a

fseo=0x1c

avsp=0x2

tosp=0x2

0xe:pti[0]      nrow=4  offs=0

0x12:pri[0]     offs=0x1c

0x14:pri[1]     offs=0x7f5

0x16:pri[2]     offs=0xfce

0x18:pri[3]     offs=0x17a7

block_row_dump:

tab 0, row 0, @0x1c

tl: 2009 fb: --H-FL-- lb: 0x0  cc: 2

col  0: [ 2]  c1 35

col  1: [2000]

 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78

tsiz: 数据区大小 

hsiz: 数据块头大小

ntab:大于1代表rac

nrow:数据块中的记录行数

frre=-1 -1代表索引

fsbo=0x1a  空闲空间起始位置 ,这里是26

fseo=0x1c  空闲空间结束位置,这里是28

avsp=0x2  可用空间。28-26=2,与bbed看到的26-24=2是一致的。

tosp=0x2   所有事务提交以后的可用空间。这里不会把分配的itl空间回收回去,因为itl还要保留来判断事务状态,所以还是2.

0xe:pti[0]      nrow=4 代表4条记录 offs=0  偏移量是0

0x12:pri[0]     offs=0x1c    第一条记录的偏移量在28的位置。

0x14:pri[1]     offs=0x7f5    第二条记录的偏移量在2037的位置。

0x16:pri[2]     offs=0xfce    第三条记录的偏移量在4046的位置。

0x18:pri[3]     offs=0x17a7    第四条记录的偏移量在6055的位置。

因为每一条记录我都把字符宽度塞满了,所以每一条记录所占大小是一样的。通过偏移量的差就能看出来。

SQL> select 6055-4046,4046-2037,2037-28 from dual;

 

 6055-4046  4046-2037    2037-28

---------- ---------- ----------

      2009       2009       2009

下面这部分的计算在我另一篇博客里面有:

http://blog.itpub.net/31480688/viewspace-2155667/

block_row_dump:

tab 0, row 0, @0x1c

tl: 2009 fb: --H-FL-- lb: 0x0  cc: 2

col  0: [ 2]  c1 35

col  1: [2000]

 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78

 

 

 

 

enq: TX – allocate ITL entry解决措施

 

基本解决思路就是增加initranspctfree参数,可以单独调整一个,也可以一起调整。

1.      alter table tablename initrans 50 | [pctfree 20];

2.      alter table tablename  move;

3.      rebuild index

 

如果不move表,只单纯的alter table的话,那么只对后面插入的数据起作用。改变全表参数除了move之外,还有数据泵和在线重定义的方法。

 

 

ITL值和数据块blocksize的关系

 

Itl虽然可以设置一个很大的值,但是一般不会达到那个最大值,因为一个itl需要24bytes空间,所以最大不会超过block_size48%,也就是说

Block_size

ITL个数

2048

41

4096

83

8192

169

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31480688/viewspace-2157157/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/31480688/viewspace-2157157/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值