SQL> ----session 1 SQL> create table t as select object_id,owner from dba_objects where rownum < 1000; 表已创建。 SQL> alter table t add constraint t_id_pk primary key(object_id); 表已更改。 SQL> select distinct dbms_rowid.rowid_block_number(rowid) block_id from t where object_id=555; BLOCK_ID ---------- 491 SQL> select distinct dbms_rowid.rowid_relative_fno(rowid) file_id from t; FILE_ID ---------- 5 SQL> select file_name,file_id from dba_data_files; FILE_NAME FILE_ID ------------------------------ ---------- /oracle/june/users01.dbf 4 /oracle/june/undotbs01.dbf 3 /oracle/june/sysaux01.dbf 2 /oracle/june/system01.dbf 1 /oracle/june/example01.dbf 5 SQL> update t set owner='killdb.com' where object_id=555; 已更新 1 行。 SQL> select xidusn,xidslot,xidsqn,ubablk,ubafil,ubarec,START_SCN from v$transaction; XIDUSN XIDSLOT XIDSQN UBABLK UBAFIL UBAREC START_SCN ---------- ---------- ---------- ---------- ---------- ---------- ---------- 6 15 916 366 3 6 968248 ----Session 2 SQL> -----session 2 SQL> select sid from v$mystat where rownum < 2; SID ---------- 29 SQL> select spid from v$process where addr=(select paddr from v$session where sid=29); SPID ------------------------ 1614 SQL> alter system flush buffer_cache; 系统已更改。 SQL> select * from t where object_id=555; OBJECT_ID OWNER ---------- ------------------------------ 555 SYS 但是 他还要读 原来的 ----Session 3 dtrace1.d脚本内容: #!/usr/sbin/dtrace -s #pragma D option quiet struct arg { int32_t arg0; int32_t arg1; int32_t arg2; int32_t arg3; }; struct arg *arg; pid$1::kkspsc0:entry{ i=0; } pid$1::kcbgtcr:entry{ i++; arg=(struct arg *)copyin(arg0,sizeof(arg)); printf("%5d %s:%s:%s:%s 0x%08x[%d,%d]\n",i,probeprov,probemod,probefunc,probename, arg->arg1,arg->arg1>>22,arg->arg1&0x3fffff); } -bash-3.2# ./dtrace1.d 1614 1 pid1614:oracle:kcbgtcr:entry 0x014001f3[5,499] --索引块 2 pid1614:oracle:kcbgtcr:entry 0x014001f5[5,501] --索引块 3 pid1614:oracle:kcbgtcr:entry 0x014001eb[5,491] --表块 4 pid1614:oracle:kcbgtcr:entry 0x00c000d0[3,208] --_SYSSMU6_112126372$ 段头 5 pid1614:oracle:kcbgtcr:entry 0x00c0016e[3,366] --_SYSSMU6_112126372$ SQL> select owner, segment_name, segment_type from dba_extents where file_id = 5 and 499 between block_id and block_id + blocks - 1 2 3 4 5 ; OWNER SEGMENT_NAME SEGMENT_TYPE ------------------------------ --------------------------------------------------------------------------------- ------------------ TEST T_ID_PK INDEX pid1614:oracle:kcbgtcr:entry 0x014001f3[5,499] ---读的是索引块 SQL> select owner, segment_name, segment_type from dba_extents where file_id = 5 and 501 between block_id and block_id + blocks - 1 2 3 4 5 ; OWNER SEGMENT_NAME SEGMENT_TYPE ------------------------------ --------------------------------------------------------------------------------- ------------------ TEST T_ID_PK INDEX SQL> select owner,segment_name,extent_id,file_id,block_id,blocks from dba_extents where segment_name='T_ID_PK'; OWNER SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS ------------------------------ --------------------------------------------------------------------------------- ---------- ---------- ---------- ---------- TEST T_ID_PK 0 5 496 8 EXTENT_ID NUMBER Extent number in the segment 在segment中extent号 BLOCK_ID NUMBER Starting block number of the extent BLOCKS NUMBER Size of the extent in Oracle blocks SQL> select owner,segment_name,header_file,header_block from dba_segments where segment_name='T_ID_PK'; OWNER SEGMENT_NAME HEADER_FILE HEADER_BLOCK ------------------------------ -------------------- ----------- ------------ TEST T_ID_PK 5 498 HEADER_FILE NUMBER ID of the file containing the segment header HEADER_BLOCK NUMBER ID of the block containing the segment header 起始块是496 块头是498 pid1614:oracle:kcbgtcr:entry 0x014001eb[5,491] ----读取的表 SQL> select owner, segment_name, segment_type from dba_extents where file_id = 5 and 491 between block_id and block_id + blocks - 1 2 3 4 5 ; OWNER SEGMENT_NAME SEGMENT_TYPE ------------------------------ --------------------------------------------------------------------------------- ------------------ TEST T TABLE pid1614:oracle:kcbgtcr:entry 0x00c000d0[3,208] SQL> select owner, segment_name, segment_type from dba_extents where file_id = 3 and 208 between block_id and block_id + blocks - 1 2 3 4 5 ; OWNER SEGMENT_NAME SEGMENT_TYPE ------------------------------ --------------------------------------------------------------------------------- ------------------ SYS _SYSSMU6_112126372$ TYPE2 UNDO SQL> select owner,segment_name,extent_id,file_id,block_id,blocks from dba_extents where segment_name='_SYSSMU6_112126372$'; OWNER SEGMENT_NAME EXTENT_ID FILE_ID BLOCK_ID BLOCKS ------------------------------ --------------------------------------------------------------------------------- ---------- ---------- ---------- ---------- SYS _SYSSMU6_112126372$ 0 3 208 8 SYS _SYSSMU6_112126372$ 1 3 216 8 SYS _SYSSMU6_112126372$ 2 3 360 8 SYS _SYSSMU6_112126372$ 3 3 11136 128 SYS _SYSSMU6_112126372$ 4 3 2304 128 读的是_SYSSMU6_112126372$ 段头 SQL> select owner,segment_name,header_file,header_block from dba_segments where segment_name='_SYSSMU6_112126372$'; OWNER SEGMENT_NAME HEADER_FILE HEADER_BLOCK ------------------------------ -------------------- ----------- ------------ SYS _SYSSMU6_112126372$ 3 208 5 pid1614:oracle:kcbgtcr:entry 0x00c0016e[3,366] SQL> select owner, segment_name, segment_type from dba_extents where file_id = 3 and 366 between block_id and block_id + blocks - 1 2 3 4 5 ; OWNER SEGMENT_NAME SEGMENT_TYPE ------------------------------ --------------------------------------------------------------------------------- ------------------ SYS _SYSSMU6_112126372$ TYPE2 UNDO SQL> select xidusn,xidslot,xidsqn,ubablk,ubafil,ubarec,START_SCN from v$transaction; XIDUSN XIDSLOT XIDSQN UBABLK UBAFIL UBAREC START_SCN ---------- ---------- ---------- ---------- ---------- ---------- ---------- 6 15 916 366 3 6 968248 完全一致: UBAFIL NUMBER Undo block address (UBA) filenum UBABLK NUMBER UBA block number 我们可以发现,在构造一致性读的时候会首先读取原表的数据块,然后读取undo segment header,定位到undo block,从而完成一致性读的构造 同样,我们也可以利用event 10200 来观察一致性读的情况,不过我这里测试发现不是太明确. SQL> conn / as sysdba 已连接。 SQL> oradebug setmypid 已处理的语句 SQL> alter system flush buffer_cache; 系统已更改。 SQL> alter system flush shared_pool; 系统已更改。 SQL> alter session set events '10200 trace name context forever,level 10'; 会话已更改。 SQL> select * from test.t where object_id=555; OBJECT_ID OWNER ---------- ------------------------------ 555 SYS SQL> alter session set events '10200 trace name context off'; 会话已更改。 SQL> oradebug close_Trace 已处理的语句 SQL> oradebug tracefile_name /oracle/app/diag/rdbms/june/june/trace/june_ora_2027.trc SQL> -bash-3.2# ./dtrace1.d 1614 1 pid1614:oracle:kcbgtcr:entry 0x014001f3[5,499] --索引块 2 pid1614:oracle:kcbgtcr:entry 0x014001f5[5,501] --索引块 3 pid1614:oracle:kcbgtcr:entry 0x014001eb[5,491] --表块 4 pid1614:oracle:kcbgtcr:entry 0x00c000d0[3,208] --_SYSSMU6_112126372$ 段头 5 pid1614:oracle:kcbgtcr:entry 0x00c0016e[3,366] --_SYSSMU6_112126372$ ktrgtc2(): started for block <0x0006 : 0x014001f3> objd: 0x00015a1e --对用T_ID_PK ktrgtc2(): started for block <0x0006 : 0x014001f5> objd: 0x00015a1e ---T_ID_PK ktrgtc2(): started for block <0x0006 : 0x014001eb> objd: 0x00015a1d ---T表 kcbchg updating CR fields for 0xbefdc960, 20972011; 0:eec1b kcbchg new CR fields for 0xbefdc960, 20972011; 0:eec1b ktrgcm(): completed for block <0x0006 : 0x014001eb> objd: 0x00015a1d ktrgtc2(): completed for block <0x0006 : 0x014001eb> objd: 0x00015a1d 这些是什么意思呢? 我们dump [5,491]块 alter system dump datafile 5 block 491; *** 2014-08-24 06:26:45.039 Dump of buffer cache at level 4 for tsn=6 rdba=20972011 BH (0xb5fb8b58) file#: 5 rdba: 0x014001eb (5/491) class: 1 ba: 0xb58b2000 set: 3 pool: 3 bsz: 8192 bsi: 0 sflg: 2 pwc: 135,19 dbwrid: 0 obj: 88605 objn: 88605 tsn: 6 afn: 5 hint: f hash: [0xbefdca18,0xe82db060] lru: [0xb5fb83c0,0xbefdd1a0] ckptq: [NULL] fileq: [NULL] objq: [NULL] objaq: [NULL] st: CR md: NULL tch: 1 cr: [scn: 0x0.ef4ce],[xid: 0x6.f.394],[uba: 0xc0016e.85.6],[cls: 0x0.ef4ce],[sfl: 0x0],[lc: 0x0.ef4ce] flags: only_sequential_access BH (0xbefdc960) file#: 5 rdba: 0x014001eb (5/491) class: 1 ba: 0xbec60000 set: 3 pool: 3 bsz: 8192 bsi: 0 sflg: 2 pwc: 135,19 BH (0xbefdc960) file#: 5 rdba: 0x014001eb (5/491) class: 1 ba: 0xbec60000 set: 3 pool: 3 bsz: 8192 bsi: 0 sflg: 2 pwc: 135,19 dbwrid: 0 obj: 88605 objn: 88605 tsn: 6 afn: 5 hint: f hash: [0xbefdcb50,0xb5fb8c10] lru: [0xbefdc918,0xbefdd2d8] ckptq: [NULL] fileq: [NULL] objq: [NULL] objaq: [NULL] st: CR md: NULL tch: 1 cr: [scn: 0x0.eec1b],[xid: 0x6.f.394],[uba: 0xc0016e.85.6],[cls: 0x0.eec1b],[sfl: 0x0],[lc: 0x0.eec1b] flags: only_sequential_access BH (0xbefdca98) file#: 5 rdba: 0x014001eb (5/491) class: 1 ba: 0xbec62000 set: 3 pool: 3 bsz: 8192 bsi: 0 sflg: 2 pwc: 135,19 dbwrid: 0 obj: 88605 objn: 88605 tsn: 6 afn: 5 hint: f hash: [0xe82db060,0xbefdca18] lru: [0xbefdcdf8,0xbefdc918] ckptq: [NULL] fileq: [NULL] objq: [0xb5fb83e8,0xdd792470] objaq: [0xdd792460,0xbefdd1d8] st: XCURRENT md: NULL fpin: 'kdswh02: kdsgrp' tch: 0 flags: block_written_once redo_since_read LRBA: [0x0.0.0] LSCN: [0x0.0] HSCN: [0xffff.ffffffff] HSUB: [1] Block header dump: 0x014001eb Object id on Block? Y seg/obj: 0x15a1d csc: 0x00.ef4ce itc: 3 flg: E typ: 1 - DATA brn: 0 bdba: 0x14001e8 ver: 0x01 opc: 0 inc: 0 exflg: 0 inc: 0 exflg: 0 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.000ec619 0x02 0x0006.00f.00000394 0x00c0016e.0085.06 ---- 1 fsc 0x0000.00000000 0x03 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000 bdba: 0x014001eb data_block_dump,data header at 0xfffffd7ffdd34a7c =============== tsiz: 0x1f80 hsiz: 0x474 pbl: 0xfffffd7ffdd34a7c 76543210 flag=-------- BH (0xbefdc960) file#: 5 rdba: 0x014001eb (5/491) class: 1 ba: 0xbec60000 set: 3 pool: 3 bsz: 8192 bsi: 0 sflg: 2 pwc: 135,19 dbwrid: 0 obj: 88605 objn: 88605 tsn: 6 afn: 5 hint: f hash: [0xbefdcb50,0xb5fb8c10] lru: [0xbefdc918,0xbefdd2d8] ckptq: [NULL] fileq: [NULL] objq: [NULL] objaq: [NULL] st: CR md: NULL tch: 1 cr: [scn: 0x0.eec1b],[xid: 0x6.f.394],[uba: 0xc0016e.85.6],[cls: 0x0.eec1b],[sfl: 0x0],[lc: 0x0.eec1b] flags: only_sequential_access