Fbird.zp
===========================================================
PCTFREE的学习总结
===========================================================

压力测试发现有一张业务表在Transations较大的时候,会出现enq: TX – index contention。由于该表主要是update操作,所以ORACLE ACS技术顾问针对该问题给出了2个建议,一个是重建该表的索引为10g支持的新特性索引:Hash-Partition Global Index;另一个就是调整该表的PCTFree,由10%调整为20%

总结一下PCTFree的知识。


PCTFREE 参数用来设置每个BLOCK中至少需要保留reserve)多少可用空间(百分比值),为数据块中已有数据update操作时可能发生的数据量增长做准备。

可以简单理解,PCTFREEBLOCK块中为update操作的预留空间。如果pctfree设置为0,即不给block预留update操作的空间,则就有可能存在update操作没有分配到ITL接口,出现ITL Wait。我们可以结合initrans参数,模拟数据库出现ITL Wait的现象。

注:以下部分主要学习了piner的新作《构建ORACLE的高可用环境》,自己动手实验的。

步骤1,创建1pctfree0initrans1的测试用表。

Pctfree设置为0 ,则如果block在完全使用的情况下不会再有free space分配新的ITL。设置initrans1,则block上默认分配的最小ITL数目为1(实际上block预留了最小2ITL接口)。

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>

步骤2test表插入数据,插满其中的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;

提交完成。

查看表testblock块的使用情况。可以看到,6070760706已经完全插满所有行。

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>

Dump60707block块的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,确实为session3sql,如下:

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死锁。

fbirdzp 发表于:2008.02.04 13:45 ::分类: ( ORACLE ) ::阅读:(241次) :: 评论 (0)

发表评论
标题

在此添加评论
表情符号: smile laughing tongue angry crying sad wassat wink

称呼

邮箱地址(可选)

个人主页(可选)




切换风格
新闻聚合
博客日历
文章归档...
最新发表...
博客统计...
网站链接...