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]
",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