HelloDBA [English]
搜索Internet 搜索 HelloDBABA
  Oracle技术站。email: fuyuncat@gmail.com  MSN: fuyuncat@hotmail.com   acoug  acoug 

关于Oracle临时表数据cache的研究

[English]

作者: fuyuncat

来源: www.HelloDBA.com

日期: 2006-12-07 14:50:13

分享到  新浪微博 腾讯微博 人人网 i贴吧 开心网 豆瓣 淘宝 推特 Facebook GMail Blogger Orkut Google Bookmarks

Global Temporary TableOracle 8i中出现的特性,可以用于存储事务或会话中的临时数据。它的出现大大方便了开发人员。但是在使用上面,由于它本身的特性,一直存在一些问题。

简单说一下临时表,它的数据只对调用它的会话可见,一个会话是无法访问其他会话中的临时表的数据。可以在创建时指定它是事务级的还是会话级的。它被创建在用户的默认临时表空间上,在创建时不会分配段,而是在会话中第一次insert的时候从零时表空间分配数据段。DML时,不会产生redo log,但是会产生undo log。并且无法生成临时表或者临时表上索引的统计信息(势必会影响CBO下的查询计划)。

下面研究一下临时表的数据是如何存储,又是如何获得的,如何cache在内存中的:

我们知道,对于普通表(regular tables),第一对表进行扫描时,会将扫描到的数据放到buffer cache中,以便以后如果有其他事务需要扫描相同数据时,直接从内存中读,而不产生disk read。并且,同时在LURMUR链中记录一个点,以决定这些数据什么时候被page out

那对于临时表呢?以前我是这样认为的,既然临时表的数据只对会话可见,那它的数据就不应该放在公用的buffer cache中,而放在每个会话的PGA里面更合适。那这个观点正确吗?我查了很多资料,并没有明确的指出临时表的数据应该是cache在内存的哪一块。由于这些都是Oracle internal的东东,没有任何公布的资料可查,我们下面来做一些试验来看看Oracle到底怎么管理临时表的数据的。

临时表中的数据到底cache在哪里?

 

首先,创建测试用的对象:

创建一张普通表:

CREATE TABLE pga_ttt (



         A      VARCHAR2(100) 



);

给表插入测试数据:

INSERT INTO pga_ttt values(1);

创建临时表:

CREATE GLOBAL TEMPORARY TABLE PGA_TEST



(



  A      VARCHAR2(3000),



  B      VARCHAR2(2000),
  C      VARCHAR2(2000)



)



ON COMMIT PRESERVE ROWS;

 

测试过程:

1.      修改db cache size为一个较小的值:

ALTER SYSTEM SET DB_CACHE_SIZE = 50M;

 

2.      重起数据库:

STARTUP FORCE

这时的数据库的内存中应该是比较干净的。

 

3.      先看一下一些什么对象已经cachebuffer cache中了:

SELECT DISTINCT objd FROM v$bh ORDER BY objd;
 
OBJD
----
2
3
6
7
8
... ...
4294967294
4294967295

这些对象应该都是系统启动时载入的一些系统对象。

 

4.      另外启动两个会话,分别执行以下语句:

INSERT INTO PGA_TEST VALUES(1, 1, 1);
SELECT * FROM PGA_TEST;

 

5.      再看下buffer cache中的对象:

SELECT DISTINCT objd FROM v$bh ORDER BY objd;
 
OBJD
----
2
3
6
7
... ...
6693385
6693513
4294967294
4294967295

这时,可以发现多出两个对象来了。但不能确定和pga_test有什么关系,也许又是两个系统对象。

 

6.      查一下pga_testobject number

SELECT object_id FROM dba_objects WHERE object_name = 'PGA_TEST';
53513

比较失望L,这个object number和刚才那两个新cachebuffer cache中的object number并不相同。但是这还并不能说明临时表的数据一定没有cachebuffer cache中去。

接下来继续测试,将buffer cache dump出来!

 

7.      Dumpbuffer cache

 level 3将整个buffer cachedump出来,这将会产生一个比较大的trace文件(折就是为什么要把buffer cache设小一些的原因)

oradebug setmypid
oradebug dump buffers 3

 

8.      打开trace文件

trace文件中,找到一下两段:

·         第一段:

BH (183EBEEC) file#: 201 rdba: 0x0066220a (1/2499082) class: 1 ba: 18114000
  set: 3 blksize: 8192 bsi: 0 set-flg: 2 pwbcnt: 574
  dbwrid: 0 obj: 6693385 objn: 53513 tsn: 3 afn: 201
  hash: [201d7a88,201d7a88] lru: [183ebff0,183ebe90]
  ckptq: [NULL] fileq: [NULL] objq: [1ea81d98,183ec044]
  st: XCURRENT md: NULL tch: 2
  flags: buffer_dirty temp_data gotten_in_current_mode redo_since_read
  LRBA: [0x0.0.0] HSCN: [0xffff.ffffffff] HSUB: [65535]
  buffer tsn: 3 rdba: 0x0066220a (1/2499082)
  scn: 0x0000.00550a09 seq: 0x00 flg: 0x08 tail: 0x0a090600
  frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x18114000 to 0x18116000
18114000 0000A206 0066220A 00550A09 08000000  [....."f...U.....]
... ...
... ...
... ...
18115830 20202020 20202020 20202020 20202020  [                ]
        Repeat 123 times
18115FF0 20202020 20202020 20202020 0A090600  [            ....]
Block header dump:  0x0066220a
 Object id on Block? Y
 seg/obj: 0x662209  csc: 0x00.00  itc: 2  flg: O  typ: 1 - DATA
     fsl: 0  fnx: 0x0 ver: 0x01
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0006.01b.00000c9d  0x0080142b.088a.20  ----    1  fsc 0x0000.00000000
0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
 
data_block_dump,data header at 0x1811405c
===============
tsiz: 0x1fa0
hsiz: 0x14
pbl: 0x1811405c
bdba: 0x0066220a
     76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x824
avsp=0x810
tosp=0x810
0xe:pti[0]    nrow=1   offs=0
0x12:pri[0]   offs=0x824
block_row_dump:
tab 0, row 0, @0x824
tl: 6012 fb: --H-FL-- lb: 0x1  cc: 3
col  0: [2000]
 31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
... ...
 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
col  1: [2000]
 31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
... ...
 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
col  2: [2000]
 31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
 ... ...
 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
end_of_block_dump

 

·         第二段:

BH (183EC04C) file#: 201 rdba: 0x0066228a (1/2499210) class: 1 ba: 18118000
  set: 3 blksize: 8192 bsi: 0 set-flg: 2 pwbcnt: 574
  dbwrid: 0 obj: 6693513 objn: 53513 tsn: 3 afn: 201
  hash: [201e8d88,183e6a5c] lru: [183ec150,183ebff0]
  ckptq: [NULL] fileq: [NULL] objq: [1ea81dd0,183ec1a4]
  st: XCURRENT md: NULL tch: 2
  flags: buffer_dirty temp_data gotten_in_current_mode redo_since_read
  LRBA: [0x0.0.0] HSCN: [0xffff.ffffffff] HSUB: [65535]
  buffer tsn: 3 rdba: 0x0066228a (1/2499210)
  scn: 0x0000.00550a08 seq: 0x00 flg: 0x08 tail: 0x0a080600
  frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x18118000 to 0x1811A000
18118000 0000A206 0066228A 00550A08 08000000  [....."f...U.....]
... ...
... ...
... ...
18119830 20202020 20202020 20202020 20202020  [                ]
        Repeat 123 times
18119FF0 20202020 20202020 20202020 0A080600  [            ....]
Block header dump:  0x0066228a
 Object id on Block? Y
 seg/obj: 0x662289  csc: 0x00.00  itc: 2  flg: O  typ: 1 - DATA
     fsl: 0  fnx: 0x0 ver: 0x01
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0005.014.00000c58  0x008044a3.060a.08  ----    1  fsc 0x0000.00000000
0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
 
data_block_dump,data header at 0x1811805c
===============
tsiz: 0x1fa0