問題:
1、Oracle DataBlock是如何存放數據的
2、當發生Update導致記錄變大時,Oracle是如何保證Rowid不變的
3、發生行遷移和行連接的條件是什麼
4、Update後留下的空間是如何被再次利用的
構造測試環境
(
ID NUMBER(10),
NAME VARCHAR2(2000),
ADRESS VARCHAR2(2000)
) tablespace test;
SQL> select b.tablespace_name,b.block_size,b.segment_space_management from dba_tablespaces b where tablespace_name='TEST';
TABLESPACE_NAME BLOCK_SIZE SEGMENT_SPACE_MANAGEMENT
------------------------------ ---------- ------------------------
TEST 8192 MANUAL 手動管理表空間
SQL> select a.pct_free,a.pct_used from all_tables a where a.table_name='MILIATEST';
PCT_FREE PCT_USED
---------- ----------
10 40
SQL> set serverout on;
SQL> exec show_space('MILIATEST');
Free Blocks.............................0
Total Blocks............................8
Total Bytes.............................65536
Unused Blocks...........................7
Unused Bytes............................57344
Last Used Ext FileId....................6
Last Used Ext BlockId...................33
Last Used Block.........................1
SQL> alter system dump datafile 6 block 33;
System altered
可以看到MILIATEST段,佔用的8塊block ,第33塊block存放了段的一些信息
Start dump data blocks tsn: 7 file#: 6 minblk 33 maxblk 33
buffer tsn: 7 rdba: 0x01800021 (6/33)
scn: 0x0000.002169b6 seq: 0x01 flg: 0x04 tail: 0x69b61001
frmt: 0x02 chkval: 0x289a type: 0x10=DATA SEGMENT HEADER - UNLIMITED
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x090C8400 to 0x090CA400
90C8400 0000A210 01800021002169B6 04010000 [....!....i!.....]
90C8410 0000289A000000000000000000000000 [.(..............]
90C8420 00000000000000010000000700001020 [............ ...]
90C8430 00000000000000000000000701800022 [............"...]
90C8440 00000000 00000000 00000000 00000000 [................]
90C8450 00000000 00000000 00000000 00000001 [................]
90C8460 00000000 0000CF2C 40000000 01800022 [....,......@"...]
90C8470 00000007000000000000000000000000 [................]
90C8480 00000000000000000000000000000000 [................]
Repeat 250 times
90C9430 00000000000100000001000100000000 [................]
90C9440 00000000000000000000000000000000 [................]
Repeat 250 times
90CA3F0 00000000000000000000000069B61001 [...............i]
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 7
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x01800022 ext#: 0 blk#: 0 ext size: 7
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Unlocked
Map Header:: next 0x00000000 #extents: 1 obj#: 53036 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x01800022 length: 7
nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 0
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
m_name varchar2(2000):='';
begin
for i in 1..10 loop
m_name:=m_name||'a';
end loop;
for j in 1..3 loop
insert into MILIATEST(ID,name) values(j,m_name);
commit;
end loop;
end;
ID NAME BLOCKID ROW#
----------- --------------- ---------- ----------
1 aaaaaaaaaa 34 0
2 aaaaaaaaaa 34 1
3 aaaaaaaaaa 34 2
m_address varchar2(2000):='';
begin
for i in 1..2000 loop
m_address:=m_address||'b';
end loop;
update MILIATEST
set ADRESS=m_address
where id=2;
commit;
end;
90C8400 0000A206 0180002200217CB3 02020000 [...."....|!.....]
90C8410 00000000 00000001 0000CF2C 00217093 [........,....p!.]
90C8420 00000000 00030002 00000000 000B0002 [................]
90C8430 00000200 00800345 00190179 00002001 [....E...y.... ..]
90C8440 00217094 002F000A 000001C5 0080014B [.p!.../.....K...]
90C8450 0016016D 00002001 00217CB3 00030100 [m.... ...|!.....]
90C8460 0018FFFF 17821789 00001782 1F8F0003 [................]
90C8470 1F6D1789 00000000 00000000 00000000 [..m.............]
90C8480 00000000 00000000 00000000 00000000 [................]
Repeat 373 times
90C9BE0 00000000 03022C00 0A03C102 61616161 [.....,......aaaa]
90C9BF0 61616161 D0FE6161 62626207 62626262 [aaaaaa...bbbbbbb]
90C9C00 62626262 62626262 62626262 62626262 [bbbbbbbbbbbbbbbb]
Repeat 123 times
90CA3C0 62626262 62626262 02012C62 0A04C102 [bbbbbbbbb,......]-更新後第1行
90CA3D0 61616161 61616161 002C6161 03C10202 [aaaaaaaaaa,.....]-第2行
90CA3E0 6161610A 61616161 2C616161 C1020200 [.aaaaaaaaaa,....]-更新前第1行(這裏的數據已經無效了,因爲第1行偏移量地址已經改變)
90CA3F0 61610A02 61616161 61616161 7CB30602 [..aaaaaaaaaa...|]—第0行
Block header dump: 0x01800022
Object id on Block? Y
seg/obj: 0xcf2c csc: 0x00.217093 itc: 2 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0002.00b.00000200 0x00800345.0179.19 --U- 1 fsc 0x0000.00217094
0x02 0x000a.02f.000001c5 0x0080014b.016d.16 --U- 1 fsc 0x0000.00217cb3
data_block_dump,data header at 0x90c845c
===============
tsiz: 0x1fa0
hsiz: 0x18
pbl: 0x090c845c
bdba: 0x01800022
76543210
flag=--------
ntab=1
nrow=3
frre=-1
fsbo=0x18
fseo=0x1789
avsp=0x1782
tosp=0x1782
0xe:pti[0] nrow=3 offs=0
0x12:pri[0] offs=0x1f8f
0x14:pri[1] offs=0x1789 –更新後第1行偏移量地址改變了,而第0行和第2行沒有影響
0x16:pri[2] offs=0x1f6d
block_row_dump:
tab 0, row 0, @0x1f8f
tl: 17 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 02
col 1: [10] 61 61 61 61 61 61 61 61 61 61
tab 0, row 1, @0x1789
tl: 2020 fb: --H-FL-- lb: 0x2 cc: 3
col 0: [ 2] c1 03
col 1: [10] 61 61 61 61 61 61 61 61 61 61
col 2: [2000]
62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62
62 62 62 62 62 62........................................................
62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62
tab 0, row 2, @0x1f6d
tl: 17 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 04
col 1: [10] 61 61 61 61 61 61 61 61 61 61
end_of_block_dump
m_address varchar2(2000):='';
m_name varchar2(2000):='';
begin
for i in 1..2000 loop
m_address:=m_address||'b';
end loop;
for i in 1..1000 loop
m_name:=m_name||'c';
end loop;
for j in 1..3 loop
update MILIATEST
set ADRESS=m_address
,name=m_name
where id=j;
commit;
end loop;
end;
buffer tsn: 7 rdba: 0x01800022 (6/34)
scn: 0x0000.0021803d seq: 0x04 flg: 0x02 tail: 0x803d0604
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
tsiz: 0x1fa0
hsiz: 0x18
pbl: 0x090c845c
bdba: 0x01800022
76543210
flag=--------
ntab=1
nrow=3
frre=-1
fsbo=0x18
fseo=0x80f
avsp=0x7f7
tosp=0x7f7
0xe:pti[0] nrow=3 offs=0
0x12:pri[0] offs=0x13dc =5084+3012byte=8096
0x14:pri[1] offs=0x13d3 =5075 +9byte=5084
0x16:pri[2] offs=0x80f +3012byte=5075
block_row_dump:
tab 0, row 0, @0x13dc
tl: 3012 fb: --H-FL-- lb: 0x0 cc: 3
col 0: [ 2] c1 02
col 1: [1000]
63636363636363636363636363636363636363636363636363
..........................................................................
63636363636363636363636363636363636363636363636363
col 2: [2000]
63636363636363636363636363636363636363636363636363
.........................................................................
63636363636363636363636363636363636363636363636363
tab 0, row 1, @0x13d3
tl: 9 fb: --H----- lb: 0x0 cc: 0列的個數爲0,表示沒有存放數據
nrid: 0x01800023.0 表示遷移的地址爲: rdba爲0x01800023,行號爲0的地方
tab 0, row 2, @0x80f
tl: 3012 fb: --H-FL-- lb: 0x2 cc: 3
col 0: [ 2] c1 04
col 1: [1000]
63636363636363636363636363636363636363636363636363
.........................................................................
63636363636363636363636363636363636363636363636363
col 2: [2000]
62626262626262626262626262626262626262626262626262
.........................................................................
62626262626262626262626262626262626262626262626262
end_of_block_dump
scn: 0x0000.0021803b seq: 0x05 flg: 0x02 tail: 0x803b0605
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x090C8400 to 0x090CA400
Block header dump: 0x01800023
Object id on Block? Y
seg/obj: 0xcf2c csc: 0x00.218039 itc: 3 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0009.00b.00000216 0x00800058.0198.1c --U- 1 fsc 0x0000.0021803b
0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x03 0x0000.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.00000000
data_block_dump,data header at 0x90c8474
===============
tsiz: 0x1f88
hsiz: 0x14
pbl: 0x090c8474
bdba: 0x01800023
76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x13be
avsp=0x13aa
tosp=0x13aa
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x13be
block_row_dump:
tab 0, row 0, @0x13be
tl: 3018 fb: ----FL-- lb: 0x1 cc: 3
hrid: 0x01800022.1 --表示這行是從rdba爲0x01800022,行號爲1的地方遷移來的
col 0: [ 2] c1 03
col 1: [1000]
62626262626262626262626262626262626262626262626262
.........................................................................
62626262626262626262626262626262626262626262626262
col 2: [2000]
62626262626262626262626262626262626262626262626262
.........................................................................
62626262626262626262626262626262626262626262626262
end_of_block_dump
1、當我們往非分區表裏插入一條數據後:在block內記錄下它的行id(安先後插入順序,從0開始),以及它在block內的偏移量地址(offs=XXXX)
oracle數據是從block底向上存放的,第一次Insert時offs從大到小
Oracle在通過rowid讀取數據時,先定位block,在通過行id,得到offs,最後得到具體值
當全表掃描時,在同一個block內數據順序是偏移量數組的順序,不是實際存放數據的順序,發生行遷移後遵循block順序