理解粗淺,僅供參考
這裏數據塊指的都是緩衝區數據塊
一致性讀文章參考: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由此組織數據