PCTFREE的学习总结

压力测试发现有一张业务表在Transations较大的时候,会出现’enq: TX �C index contention’。由于该表主要是update操作,所以ORACLE ACS技术顾问针对该问题给出了2个建议,一个是重建该表的索引为10g支持的新特性索引:Hash-Partition Global Index;另一个就是调整该表的PCTFree,由10%调整为20%。
        总结一下PCTFree的知识。
        PCTFREE参数用来设置每个BLOCK中至少需要保留(reserve)多少可用空间(百分比值),为数据块中已有数据update操作时可能发生的数据量增长做准备。如下,PCTFREE=20时:
         PCTFREE的学习总结
        可以简单理解,PCTFREE是BLOCK块中为update操作的预留空间。如果pctfree设置为0,即不给block预留update操作的空间,则就有可能存在update操作没有分配到ITL接口,出现ITL Wait。我们可以结合initrans参数,模拟数据库出现ITL Wait的现象。
        注:以下部分主要学习了piner的新作《构建ORACLE的高可用环境》,自己动手实验的。
步骤1,创建1个pctfree为0,initrans为1的测试用表。
        Pctfree设置为0,则如果block在完全使用的情况下不会再有free space分配新的ITL。设置initrans为1,则block上默认分配的最小ITL数目为1(实际上block预留了最小2个ITL接口)。
SQL> create table test (a number) pctfree 0 initrans 1;                 
表已创建。                                                    
SQL>                                                          
SQL> select pct_free,ini_trans from user_tables where table_name = 'TEST';
 PCT_FREE INI_TRANS                                         
---------- ----------
        0         1                                         
SQL>                                      
 
步骤2,test表插入数据,插满其中的block块。
SQL> begin                                   
 2 for i in 1..2000 loop                       
 3 insert into test values(i) ;                   
 4 end loop;                               
 5 end;                                   
 6 /                                      
PL/SQL过程已成功完成。                     
SQL> commit;                                
提交完成。                                  
 
查看表test的block块的使用情况。可以看到,60707与60706已经完全插满所有行。
SQL> select f,b,count(*) from (                   
 2 select dbms_rowid.rowid_relative_fno(rowid) f,
 3 dbms_rowid.rowid_block_number(rowid) b   
 4 from test) group by f,b;                    
        F         B  COUNT(*)           
---------- ---------- ----------
        1     60707       734            
        1     60708       532           
        1     60706       734           
SQL>
Dump出60707block块的trace文件
SQL> alter system dump datafile 1 block 60707;
系统已更改。
 
步骤3,在已经完全使用的block上执行update操作。
        根据预期,没有预留空间的情况下,新的session在不能分配到ITL接口的情况下会出现ITL等待。我们在已经完全使用的block.60707上分别打开3个不同的Session,对不同的rowid进行update操作,如下:
Session1:
SQL> update test set a=a                                 
 2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=60707
 3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=1;      
已更新1行。                                        
SQL>                                                 
Session2:
SQL> update test set a=a                                 
 2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=60707
 3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=2;      
已更新1行。                                        
SQL>                                                 
Session3:实际的测试中,session出现等待,无法返回结果。
SQL> update test set a=a                                 
 2 where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=60707
 3 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3;      
 
步骤4,确认数据库存在ITL等待事件如下,
SQL> select sid, EVENT from v$session_wait where sid='142';
 
      SID EVENT
---------- ----------------------------------------------------------------
      142 enq: TX - allocate ITL entry
查看数据库当前的sql,确实为session3的sql,如下:
SQL> SELECT username, sql_text from v$session a, v$sqltext b                               
 2 where a.sql_address =b.address and a.username= 'SYS' and a.sid= '142' order by address, piece;
 
USERNAME  SQL_TEXT                         
---------- ----------------------------------------------------------------
SYS       update test set a=a where dbms_rowid.ROWID_BLOCK_NUMBER(rowid)=6
SYS       0707 and dbms_rowid.ROWID_ROW_NUMBER(rowid)=3
SQL>
 
        上面试模拟产生ITL等待的场景,主要是为了自己学习验证pctfree的功能,实际上在大量并发下也会产生row lock,即ITL死锁。

你可能感兴趣的:(职场,学习笔记,pctfree,休闲)