一條UPDATE從生到死的整個過程的深入解析

本文引用ITPUB上的一篇文章一條UPDATE從生到死的整個過程的深入解析
http://www.itpub.net/thread-1780068-1-1.html

 

這是曾經Oracle原廠的一位兄弟問我的一個問題,後來也有些人問起這個問題:
  用
ORACLE內部原理描述以下過程:
1、sqlplus gyj/gyj@orcl
2、updatet_gyj set name='gyj1' where id=1;
3、commit;
4、exit

      一看這個問題是不是灰常複雜,阿里系的童鞋特別喜歡用類似這樣的題目面試人,從中可以快速的判斷你是哪個級別的DBA(初級/中級/高級),在這個問題上我給大家拋磚迎玉,由於能力有限只能做簡單解釋,歡迎大家一起參與討論並補充。嘿嘿!這是個很理論的東東希望對大家在處理實際問題的時候有一點點幫助。

1、sqlplus gyj/gyj@orcl
這一塊涉及到Oracle的網絡連接的知識點。我們先來看一幅描述Oracle客戶端與服務器網絡連接的圖,並給出了連接的整個步驟:

111111.png

2013-4-12 10:00 上傳
下載附件(246.57 KB)



(1)客戶端SQL Plus請求連接,監聽接受客戶端的TCP連接,並獲取客戶端發過來的TNS數據包。


2)監聽進程打開用於與子進程通信的管道,同時fork一個子進程,稱爲“監聽子進程1”的子進程,然後監聽進程一直等待,直到這個“監聽子進程1”結束。


3)監聽子進程1 Fork出子進程2。


4)完成上面一步,子進程1馬上退出並結束子進程1。


5)子進程2收集本進程所在的主機名、IP地址及進程號等信息,並把子進程2重名成server process(這裏我們也把server process叫前臺進程或叫服務器進程),申請佔用一小塊PGA內存。


6)前臺進程把主機名、IP地址及進程號發送給監聽進程。


7)監聽進程收到前臺進程的信息,並返回客戶端的信息(比如用戶密碼環境變量等)給前臺進程。


8)前臺進程查詢USER$、PROFILE$等數據字典,校驗用戶名密碼是否合法,如果用戶密碼錯誤就報錯用戶名密碼無效,否則就與客戶端進行交互。


9)客戶端收到前臺進程的信息與之交互,整個連接創建完成。



2、update t_gyj set name='gyj1' where id=1;

當這條sql發出來時,Oracle要做些什麼呢?我們先來看一張圖(來自DSI405的Library cache)



2222222.png

2013-4-12 10:00 上傳
下載附件(19.4 KB)

 

在整個SGA中最複雜的就是sharedpool,而shared pool中最複雜就是library cache,這裏對它的機制不做詳細討論,簡單講講sql在裏面的運作流程。


首先sql(update t_gyjset name='gyj1' where id=1)的每個字符當然包括空格轉化成ASCII碼後,再拿這一堆ASCII碼通過HASH函數生成一個sql_hash值,Oracle拿着這個sql_hash值去描掃HASH Buckets(看上面的圖,這個幅畫的不太好,只畫了0號的HASH BUCKETS),假如剛好sql_hash值=0,那麼Oracle就延着0號HASH Buckets去搜索Object Handle鏈,在這個Object Handle上存有sql的文本,如果和我們的update t_gyj set name='gyj1' where id=1一模一樣對上,那就說明這條sql已被緩存在共享池了,這個過程就是軟解析。當然再往下我就不說了,再說下去很複雜了父子游標,最後執行計劃是被存放在堆6中。


   好,那麼如果通過上面的方式在Object Handle鏈沒搜索到這條sql的文本,那說明sql不在共享池中,這個時侯就要做硬解析(過程大要做語法,語義,權限,查詢視圖展開、劃分小的查詢塊、sql等價轉換、代價估算、最後生成執行計劃),這個代價會有點高,如果有大量的硬解析那會消耗CPU和佔用共享池。

   其實解析還有:軟軟解析、無解析。。。。嘻嘻!這裏不細說了,先簡單說到這裏,我們再往下看。

(一)如果ID列上無索引
(1)查詢SEG$等數據字典,找到T_GYJ表段頭
(2)從段頭讀出Extent Map,開始全掃描
(3)找到第一個滿足條件的行,進行修改
(4)查找同一塊中剩下的行,先構造一個CR塊,在CR塊中繼續查找,如果又找到滿足條件的行,在Xcur塊中修改。

(二)如果ID列上有索引,且版本不是11GR1(10G、11GR2),則不需要構造CR塊

(三)ID列無論是否有索引,在11GR1下都需要構造CR塊。

(四)如果NAME列上有索引,增加索引維護步驟:
(1)先在原索引塊中刪除要修改的原值
(2)、再將新值插入

(五)任何塊的修改,都有以下步驟(非IMU)
(1)在PGA中生成UNDO段頭事務表的後映像(5.2)
(2)在PGA中生成UNDO塊的後映像(5.1)
(3)在PGA中生成DataBlock塊的後映像(11.9)
(4)將前三個Redo矢量做爲一條Redo Recorder寫入Log buffer
(5)修改UNDO段頭的事務表,事務正式開始。
(6)修改UNDO塊,寫入DataBlock的前映像。
(7)修改DataBlock,將新值“gyj1”寫入Buffer cache。

(六)任何塊的修改,都有以下步驟(IMU)
(1)在PGA中生成DataBlock塊的後映像(11.9)
(2)在PGA中生成UNDO段頭事務表的後映像(5.2)
(3)在PGA中生成UNDO塊的後映像(5.1)
(4)將前三個Redo矢量做爲一條Redo Recorder寫入Shared pool中的Private strand。
(5)將DataBlock中的前映像值,寫入Shared pool中的Imu pool。
(6)修改UNDO段頭的事務表。
(7)修改UNDO塊,寫入DataBlock的前映像。
(8)修改DataBlock,將新值“gyj1”寫入Buffer cache。

3、commit;
(一)非IMU下(按最常見的快速提交):
(1)在PGA中生成Commit的Redo 信息(編號5.4),另做爲一條Redo recorder,寫入Log buffer
(2)修改事務表相應Slot,聲明事務已提交。
(3)修改DataBlock,在ITL Slot中寫入快速提交標誌和SCN。每行上的行鎖不清0。
(4)通知Lgwr,將Log buffer寫入Redo file。
(5)收到Lgwr通知,寫入完成。
(6)向用戶發收提交完成信息。

(一)IMU下(按最常見的快速提交):
(1)在PGA中生成Commit的Redo 信息(編號5.4),傳入Shared pool中的Private strand,追加在事務之前的Redo recorder之後。
(2)修改事務表相應Slot,聲明事務已提交。
(3)修改DataBlock,在ITL Slot中寫入快速提交標誌和SCN。每行上的行鎖不清0。
(4)將Private Strand中的Redo數據寫入Log buffer。
(5)通知Lgwr,將Log buffer寫入Redo file。
(6)收到Lgwr通知,寫入完成。
(7)向用戶發收提交完成信息。

4、exit
(1)、斷開連接,中止服務器進程,釋放PGA

最後附:dump的信息(針對update t_gyj set name='gyj1' where id=1;),有興趣大家可以去dump一下這樣可以更深入瞭解Oracle,使之成爲自己的體系結構。


1.      redolog的dump

alter system dump logfile '/u01/app/oracle/oradata/ocm/redo02.log ';

REDO RECORD - Thread:1 RBA:0x0000d4.00000088.015c LEN: 0x00a4 VLD: 0x01
SCN: 0x0000.00f5e121 SUBSCN:  1 04/12/2013 08:45:43
CHANGE #1 TYP:0 CLS:23 AFN:6 DBA:0x018000b0OBJ:4294967295 SCN:0x0000.00f5e120 SEQ:1 OP:5.4 ENC:0 RBL:0
ktucm redo: slt: 0x0013 sqn: 0x00005a4dsrt: 0 sta: 9 flg: 0x2 ktucf redo: uba: 0x01800c05.0747.34 ext: 6 spc: 578 fbi:0
CHANGE #2 MEDIA RECOVERY MARKERSCN:0x0000.00000000 SEQ:0 OP:24.4 ENC:0

REDORECORD - Thread:1 RBA: 0x0000d4.00000089.0010 LEN: 0x0214 VLD: 0x05
SCN: 0x0000.00f5e123 SUBSCN:  1 04/12/2013 08:45:48
CHANGE #1 TYP:0 CLS:17 AFN:6 DBA:0x01800080OBJ:4294967295 SCN:0x0000.00f5e114 SEQ:1 OP:5.2 ENC:0 RBL:0
ktudh redo: slt: 0x0018 sqn: 0x000057efflg: 0x0012 siz: 164 fbi: 0
           uba: 0x018021ba.0724.0f   pxid:  0x0000.000.00000000
CHANGE #2 TYP:0 CLS:18 AFN:6 DBA:0x018021baOBJ:4294967295 SCN:0x0000.00f5e113 SEQ:1 OP:5.1 ENC:0 RBL:0
ktudb redo: siz: 164 spc: 6094 flg: 0x0012seq: 0x0724 rec: 0x0f
           xid:  0x0001.018.000057ef
ktubl redo: slt: 24 rci: 0 opc: 11.1 [objn:77365 objd: 77365 tsn: 7]
Undo type: Regular undo        Begintrans    Last buffer split:  No
Temp Object:  No
Tablespace Undo:  No
            0x00000000  prev ctl uba:0x018021ba.0724.0e
prev ctl max cmt scn:  0x0000.00f5dc35  prev tx cmt scn:  0x0000.00f5dc3f
txn start scn:  0xffff.ffffffff  logon user: 91  prev brb: 25174454  prev bcl: 0 BuExt idx: 0 flg2: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: URP row dependencies Disabled
CHANGE #2 MEDIA RECOVERY MARKERSCN:0x0000.00000000 SEQ:0 OP:24.4 ENC:0

REDO RECORD - Thread:1 RBA:0x0000d4.00000089.0010 LEN: 0x0214 VLD: 0x05
SCN: 0x0000.00f5e123 SUBSCN:  1 04/12/2013 08:45:48
CHANGE #1 TYP:0 CLS:17 AFN:6 DBA:0x01800080OBJ:4294967295 SCN:0x0000.00f5e114 SEQ:1 OP:5.2 ENC:0 RBL:0
ktudh redo: slt: 0x0018 sqn: 0x000057efflg: 0x0012 siz: 164 fbi: 0
           uba: 0x018021ba.0724.0f   pxid:  0x0000.000.00000000
CHANGE #2 TYP:0 CLS:18 AFN:6 DBA:0x018021baOBJ:4294967295 SCN:0x0000.00f5e113 SEQ:1 OP:5.1 ENC:0 RBL:0
ktudb redo: siz: 164 spc: 6094 flg: 0x0012seq: 0x0724 rec: 0x0f
           xid:  0x0001.018.000057ef
ktubl redo: slt: 24 rci: 0 opc: 11.1 [objn:77365 objd: 77365 tsn: 7]
Undo type: Regular undo        Begintrans    Last buffer split:  No
Temp Object:  No
Tablespace Undo:  No
            0x00000000  prev ctl uba:0x018021ba.0724.0e
prev ctl max cmt scn:  0x0000.00f5dc35  prev tx cmt scn:  0x0000.00f5dc3f
txn start scn:  0xffff.ffffffff  logon user: 91  prev brb: 25174454  prev bcl: 0 BuExt idx: 0 flg2: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000  bdba:0x00c0027d  hdba: 0x00c0027a
itli: 2 ispac: 0  maxfr: 4858
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0ckix: 0
ncol: 2 nnew: 1 size: 2
col 1: [ 6]  41 41 41 41 41 41
CHANGE #3 TYP:2 CLS:1 AFN:3 DBA:0x00c0027dOBJ:77365 SCN:0x0000.00f5e0cc SEQ:1 OP:11.5 ENC:0 RBL:0
KTB Redo
op: 0x11 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: F xid:  0x0001.018.000057ef    uba: 0x018021ba.0724.0f
Block cleanout record, scn:  0x0000.00f5e123 ver: 0x01 opt: 0x02, entriesfollow...
itli: 1  flg: 2  scn: 0x0000.00f5e0cc
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000  bdba:0x00c0027d  hdba: 0x00c0027a
itli: 2 ispac: 0  maxfr: 4858
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 2ckix: 0
ncol: 2 nnew: 1 size: -2
col 1: [ 4]  67 79 6a 31
CHANGE #4 MEDIA RECOVERY MARKERSCN:0x0000.00000000 SEQ:0 OP:5.20 ENC:0
session number   = 162
serial number   = 7
transaction name =
version 186646784
audit sessionid 1362603
Client Id =

2.      undo的dump

(1)    對應OP=5.2的操作

alter system dump undo header"_SYSSMU1_1918248848$";


index  state cflags wrap#    uel         scn            dba            parent-xid    nub    stmt_num    cmt

------------------------------------------------------------------------------------------------

0x18   10    0x80 0x57ef  0x0010  0x0000.00f5e123  0x018021ba 0x0000.000.00000000 0x00000001   0x00000000  0



(2)    對應OP=5.1的操作,即undo塊數據

alter systemdump datafile 6 block 8634;

* Rec #0xf  slt:0x18  objn: 77365(0x00012e35)  objd: 77365 tblspc: 7(0x00000007)

*       Layer: 11 (Row)   opc: 1   rci 0x00  
Undotype:  Regular undo    Begin trans    Last buffer split:  No 
TempObject:  No 
TablespaceUndo:  No 
rdba:0x00000000Ext idx: 0
flg2: 0
*-----------------------------
uba:0x018021ba.0724.0e ctl max scn: 0x0000.00f5dc35 prv tx scn: 0x0000.00f5dc3f
txn startscn: scn: 0x0000.00f5e123 logon user: 91
prev brb: 25174454 prev bcl: 0
KDO undorecord:
KTB Redo 
op:0x03  ver: 0x01  
compatbit: 4 (post-11) padding: 1
op: Z
KDO Opcode: URP row dependencies Disabled
  xtype: XA flags: 0x00000000  bdba: 0x00c0027d  hdba: 0x00c0027a
itli:2  ispac: 0  maxfr: 4858
tabn: 0slot: 0(0x0) flag: 0x2c lock: 0 ckix: 0
ncol: 2nnew: 1 size: 2
col  1: [ 6]  41 41 41 41 41 41

3.      data的dump

對應OP=11.9的操作
alter system dump datafile 3 block 637

Object idon Block? Y
seg/obj: 0x12e35  csc: 0x00.f5e123  itc: 2 flg: E  typ: 1 - DATA
     brn: 0 bdba: 0xc00278 ver: 0x01 opc: 0
     inc: 0 exflg: 0

Itl          Xid                  Uba         Flag Lck        Scn/Fsc
0x01   0x0003.00d.00007825  0x01802b0c.0a53.2d  C---   0  scn 0x0000.00f5e0cc
0x02   0x0001.018.000057ef  0x018021ba.0724.0f  ----   1  fsc 0x0002.00000000
bdba:0x00c0027d
data_block_dump,dataheader at 0xa5d664
===============
tsiz:0x1f98
hsiz:0x14
pbl:0x00a5d664
     76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1f80
avsp=0x1f77
tosp=0x1f79
0xe:pti[0]      nrow=1 offs=0
0x12:pri[0]     offs=0x1f80
block_row_dump:
tab 0,row 0, @0x1f80
tl: 11fb: --H-FL-- lb: 0x2  cc: 2
col  0: [ 2] c1 02
col  1: [ 4]  67 79 6a 31
  

附OPCODE:
Layer 5 : Transaction Undo -  KCOCOTUN    [ktucts.h]
        Opcode 1 : Undo block or undo segment header - KTURDB
        Opcode 2 : Update rollback segment header - KTURDH
        Opcode 3 : Rollout a transaction begin 
        Opcode 4 : Commit transaction (transaction table update) 
- no undo record 
        Opcode 5 : Create rollback segment (format) - no undo record 
        Opcode 6 : Rollback record index in an undo block - KTUIRB
        Opcode 7 : Begin transaction (transaction table update) 
        Opcode 8 : Mark transaction as dead 
         Opcode 9 : Undo routine to rollback theextend of a rollback segment 
        Opcode 10 :Redo to perform the rollback of extend of rollback segment 
                    to the segment header. 
        Opcode 11 :Rollback DBA in transaction table entry - KTUBRB 
        Opcode 12 :Change transaction state (in transaction table entry) 
        Opcode 13 :Convert rollback segment format (V6 -> V7) 
        Opcode 14 :Change extent allocation parameters in a rollback segment 
        Opcode 15 :
         Opcode 16 :
        Opcode 17 :
        Opcode 18 :
        Opcode 19 : Transaction start audit log record
        Opcode 20 : Transaction continue audit log record     
        Opcode 24 : Kernel Transaction Undo Relog CHanGe – KTURLGU
Layer 11 : Row Access -  KCOCODRW    [kdocts.h]
        Opcode 1 : Interpret Undo Record (Undo) 
        Opcode 2 : Insert Row Piece 
        Opcode 3 : Drop Row Piece 
        Opcode 4 : Lock Row Piece 
        Opcode 5 : Update Row Piece 
        Opcode 6 : Overwrite Row Piece 
        Opcode 7 : Manipulate First Column (add or delete the 1rst column) 
        Opcode 8 : Change Forwarding address 
        Opcode 9 : Change the Cluster Key Index 
        Opcode 10 :Set Key Links (change the forward & backward key links 
                    on a cluster key) 
        Opcode 11 :Quick Multi-Insert (ex: insert as select …) 
        Opcode 12 :Quick Multi-Delete 
        Opcode 13 :Toggle Block Header flags

注:11.19是在11g中才有,是11.5的改進update操作碼。

  Oracle的魅力也許就在於任何一個小概念都可以講出一大堆東西, 這裏沒有涉及到鎖、Latch、Mutex等,要整的東西太實在太多了,這幾個步驟完完整整寫下來可以出一本書了,涉及到Oracle的方方面面。

 

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