ORACLE 數據塊、ITL SELECT和UPDATE邏輯梳理

理解粗淺,僅供參考


這裏數據塊指的都是緩衝區數據塊

一致性讀文章參考:http://hi.baidu.com/edeed/item/7aff6ee4b3f0870f8d3ea8b3

DUMP數據塊文章參考:http://blog.163.com/dazuiba_008/blog/static/363349812012111111399549


ORACLE 9.2.0

DUMP的意思是查看一個數據塊的內容

PLSQL命令窗口由ROWID查找數據塊位置,普通權限用戶

SQL> select t.*,dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block# from test_user t;
 
        ID        AGE NAME           FILE#     BLOCK#
---------- ---------- --------- ---------- ----------
         1        999 tommy              1      85546
         2        999 jerry              1      85546
         3        999 henry              1      85546
         4        999 hibernate          1      85546
         5        999 birt               1      85546
         6        999 garden             1      85546
         7        999 green              1      85546
         8        999 green              1      85546
         9        999 green              1      85546
        10        999 green              1      85546
 
10 rows selected
對應文件號、塊號

ALTER SYSTEM CHECKPOINT;手動刷新緩存到數據文件,沒有這一步,物理文件可能與緩衝區內容不一致,DBWN參考http://blog.chinaunix.net/uid-24501667-id-3028586.html
ALTER SYSTEM DUMP DATAFILE 1 BLOCK 85546;生成BLOCK對應的TRACE文件
第一次DUMP生成一個.trc(TRACE)文件,以後的DUMP會把結果附加到文件裏面,以時間分別。

進入LINUX ORACLE目錄

$ pwd
/oracle/product/9.2.0/admin/***
$ ll
total 16
drwxr-xr-x   2 oracle     oinstall        96 Jan 17 10:40 adump
drwxr-xr-x   2 oracle     oinstall      4096 May 13 10:12 bdump
drwxr-xr-x   2 oracle     oinstall        96 Jan 17 10:40 cdump
drwxr-xr-x   2 oracle     oinstall        96 Jan 17 11:48 create
drwxr-xr-x   2 oracle     oinstall        96 Jan 17 10:40 hdump
drwxr-xr-x   2 oracle     oinstall        96 Jan 17 11:48 pfile
drwxr-xr-x   2 oracle     oinstall        96 Jan 17 11:48 scripts
drwxr-xr-x   2 oracle     oinstall      4096 May 23 14:23 udump
$ 

在*DUMP文件夾裏面找。我的文件在UDUMP目錄。

$ cd udump
$ ls -lt
total 176
-rw-r-----   1 oracle     oinstall     18660 May 23 16:19 ***_ora_7997.trc
-rw-r-----   1 oracle     oinstall      5582 May 23 10:23 ***_ora_3771.trc
-rw-r-----   1 oracle     oinstall      1725 May 13 10:13 ***_ora_14056.trc
-rw-r-----   1 oracle     oinstall      3720 Apr 19 18:41 ***_ora_1205.trc
-rw-r-----   1 oracle     oinstall      3390 Apr 19 18:22 ***_ora_28836.trc
...
以更新時間排序。
然後可以more vi cat 看文件內容了。


先說說我對於一致性讀的理解

一致性讀文章參考:http://hi.baidu.com/edeed/item/7aff6ee4b3f0870f8d3ea8b3

SQL執行計劃有Consistent gets 和 db block gets,很多文章說前者是讀UNDO塊,讓人誤解,其實這兩個命名是有道理的。前者指需要保證一致性讀從而讀到的數據塊,從而可能讀到UNDO BLOCK,也可能不會,後者相反指不需保證一致性,完全從DATA BLOCK讀取。比如SELECT必須保證一致性讀,UPDATE不需要,會選擇db block gets從數據塊直接讀。

借用上面鏈接的例子,分析一下數據塊和ITL、UNDO塊。

表TB1,1W條記錄,第一萬條記錄在數據塊在DB1,上一次更新在8:50,用戶A在9:00遍歷全表,需要15分鐘到達最後一行,9:15讀到的數據應該是9:00時刻的快照結果,而無論期間有沒有更新,提交未提交。這就是一致性讀。

9:00 DB1中的ITL信息爲:SCN850    UNDO1/提交標誌、事務號等

9:10用戶B修改最後一行,不管提交未提交,DB1中ITL信息爲:SCN910   UNDO2,其他

(更新與提交都會修改SCN,SCN結果會被修改兩次,數據塊頭也有一個SCN,ITL中也有一個SCN,這些先不管)

ITL顯示的信息是,數據塊最後一次修改的流水號,此次修改以前數據保存的回滾段位置(更新數據會立即更新數據塊,不管提交未提交,同時保存更新前數據到UNDO表空間),進入UNDO2,可以看到其中除了包含本次事務前的數據(或者其他能夠完成回滾的操作數據),還有一個ITL,這個ITL是從數據塊DB1裏面複製過來的,DB1中更新ITL爲SCN910之前先把其中數據複製到UNDO2,所以UNDO2中ITL爲:SCN850 UNDO1,其他


9:11用戶C修改數據塊DB1,ITL變爲:SCN911  UNDO3,其他

UNDO3中ITL爲:SCN910   UNDO2,其他


9:15查詢到數據塊DB1時,發現SCN911大於查詢SCN900,於是進入UNDO3,發現SCN910依然大過900,進入UNDO2,OK,然後由UNDO2和UNDO3裏面的回滾操作數據組織出8:50DB1的數據,OK

ORA-01555快照過舊。更新數據如果提交的話,ITL有提交標誌,提交後UNDO BLOCK允許被覆蓋(這裏超時時間好像可以設置)

如果9:10更新被提交,UNDO2標記已提交,然後9:12被其他事務覆蓋,其中ITL爲SCN912  UNDO4,其他

9:15查詢到達的時候,根據UNDO3找到UNDO2塊,發現其中SCN912大過UNDO3中的SCN911,拋出此異常。顯然,根本重現不了9:00時刻的數據快照了。


-----------------------------------------------------------------------一致性讀OVER----------------------------------------------------------------------------

-----------------------------------------------------------------------UPDATE做了哪些工作 開始------------------------------------------------------------------------

參考http://zhidao.baidu.com/question/480089238.html


個人理解。

UPDATE過程中主要實現兩件事,行鎖和回滾支持,這裏只關心數據塊的改動。

申請到undo資源,寫入數據->在數據塊頭ITL表中申請一個空表項,寫入數據->在每條要修改的記錄行的行頭寫入申請到的ITL索引->更新數據

在四個SESSION中執行四條不同的UPDATE修改四條數據。幾分鐘後提交兩條數據,另外兩條未提交。
可見ITL中FLAG的--U--標誌,意思是已提交但是提交操作在更新操作很久以後。
----是未提交。--C--是
--- flag     1 nibble   ---- = transaction is active, or committed pending cleanout
---                     C--- = transaction has been committed and locks cleaned out
---                     -B-- = this undo record contains the undo for this ITL entry
---                     --U- = transaction committed (maybe long ago); SCN is an upper bound
---                     ---T = transaction was still active at block cleanout SCN


*** 2013-05-23 15:53:31.242
Start dump data blocks tsn: 0 file#: 1 minblk 85546 maxblk 85546
buffer tsn: 0 rdba: 0x00414e2a (1/85546)
scn: 0x0000.059dfd7b seq: 0x01 flg: 0x02 tail: 0xfd7b0601
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump:  0x00414e2a
 Object id on Block? Y
 seg/obj: 0xcabd  csc: 0x00.59dfd09  itc: 4  flg: O  typ: 1 - DATA
     fsl: 0  fnx: 0x0 ver: 0x01
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0003.02d.0000ea56  0x0080002f.195a.13  ----    1  fsc 0x0000.00000000
0x02   0x0002.00c.0000eb42  0x00800020.1bf1.27  ----    1  fsc 0x0000.00000000
0x03   0x000a.00d.0000b2aa  0x0080029d.109e.47  --U-    1  fsc 0x0000.059dfd7b
0x04   0x0004.019.0000b27e  0x0080003e.16b2.2a  --U-    1  fsc 0x0000.059dfd79
 
data_block_dump,data header at 0x8000000100193c8c
===============
tsiz: 0x1f70
hsiz: 0x26
pbl: 0x8000000100193c8c
bdba: 0x00414e2a
     76543210
flag=--------
ntab=1
nrow=10
frre=-1
fsbo=0x26
fseo=0x1dc8
avsp=0x1ea6
tosp=0x1ea6
0xe:pti[0]      nrow=10 offs=0
0x12:pri[0]     offs=0x1ef3
0x14:pri[1]     offs=0x1ee3
0x16:pri[2]     offs=0x1e3c
0x18:pri[3]     offs=0x1e28
0x1a:pri[4]     offs=0x1e19
0x1c:pri[5]     offs=0x1e08
0x1e:pri[6]     offs=0x1df8
0x20:pri[7]     offs=0x1de8
0x22:pri[8]     offs=0x1dd8
0x24:pri[9]     offs=0x1dc8
block_row_dump:
tab 0, row 0, @0x1ef3
tl: 16 fb: --H-FL-- lb: 0x1  cc: 3
col  0: [ 2]  c1 02
col  1: [ 3]  c2 0b 02
col  2: [ 5]  74 6f 6d 6d 79
tab 0, row 1, @0x1ee3
tl: 16 fb: --H-FL-- lb: 0x0  cc: 3
col  0: [ 2]  c1 03
col  1: [ 3]  c2 0b 02
col  2: [ 5]  6a 65 72 72 79
tab 0, row 2, @0x1e3c
tl: 16 fb: --H-FL-- lb: 0x2  cc: 3
col  0: [ 2]  c1 04
col  1: [ 3]  c2 0b 02
col  2: [ 5]  68 65 6e 72 79
tab 0, row 3, @0x1e28
tl: 20 fb: --H-FL-- lb: 0x3  cc: 3
col  0: [ 2]  c1 05
col  1: [ 3]  c2 0b 02
col  2: [ 9]  68 69 62 65 72 6e 61 74 65
tab 0, row 4, @0x1e19
tl: 15 fb: --H-FL-- lb: 0x4  cc: 3
col  0: [ 2]  c1 06
col  1: [ 3]  c2 0b 02
col  2: [ 4]  62 69 72 74
tab 0, row 5, @0x1e08
tl: 17 fb: --H-FL-- lb: 0x0  cc: 3
col  0: [ 2]  c1 07
col  1: [ 3]  c2 0a 64
col  2: [ 6]  67 61 72 64 65 6e
tab 0, row 6, @0x1df8
tl: 16 fb: --H-FL-- lb: 0x0  cc: 3
col  0: [ 2]  c1 08
col  1: [ 3]  c2 0a 64
col  2: [ 5]  67 72 65 65 6e
tab 0, row 7, @0x1de8
tl: 16 fb: --H-FL-- lb: 0x0  cc: 3
col  0: [ 2]  c1 09
col  1: [ 3]  c2 0a 64
col  2: [ 5]  67 72 65 65 6e
tab 0, row 8, @0x1dd8
tl: 16 fb: --H-FL-- lb: 0x0  cc: 3
col  0: [ 2]  c1 0a
col  1: [ 3]  c2 0a 64
col  2: [ 5]  67 72 65 65 6e
tab 0, row 9, @0x1dc8
tl: 16 fb: --H-FL-- lb: 0x0  cc: 3
col  0: [ 2]  c1 0b
col  1: [ 3]  c2 0a 64
col  2: [ 5]  67 72 65 65 6e
end_of_block_dump

其中行頭lb指向的就是ITL索引

有幾個事務,ITL就有幾條記錄

seg/obj:對象ID,查DBA_OBJECTS 可查到表名,進制轉換to_char(123,’xxx’)、TO_NUMBER(’19F’,’XXX’)、bin_to_num(1,1,0,1)

bdba:數據塊所在文件號和數據塊號

         0x00414e2a換成二進制0000 0000 0100 0001 0100 1110 0010 1010,取前十位是文件號,後面部分表示塊號,14e2a的十進制爲85546

nrow 該塊上數據行數量

tl: 16行大小字節數  cc: 3列數    字節值由 DUMP(1,'16')或者 DUMP('TOMMY','16')得到,[]裏面爲字節數

XID   0x0003.02d.0000ea56
          查V$TRANSACTION其中0003對應XIDUSN,02d對應XIDSLOT,0000ea56對應XIDSQN   
UBA  0x00c02d8a.0090.20 

        ->0000000011=3號文件,0x2d8a=11658號塊,0x90=undo塊被覆蓋144次,0x20=第32條undo記錄

-------------------------------------------------------------------UPDATE OVER-----------------------------------------------------------------------------

-------------------------------------------------------------------SELECT 開始-----------------------------------------------------------------------------

表TB1 9:00有兩條記錄都是ABC

9:10用戶A改第一條爲XYZ未提交

9:11用戶B改第二條爲UVW立即提交

9:15用戶C查表結果爲ABC、UVW

而數據塊的記錄很明顯是XYZ、UVW

猜測,讀取一行數據時,找到ITL,0自然就不管了,判斷ITL提交狀態,未提交時會進入UNDO BLOCK由此組織數據

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章