oracle內核原理-IMU

深入解析Oracle IMU模式下的REDO格式
1. 什麼是IMU?IMU的主要作用是什麼,也就是說爲了解決什麼問題?
IMU--->In Memory Undo,10g新特性,數據庫會在shared pool開闢獨立的內存區域用於存儲Undo信息,
每個新事務都會分配一個IMU buffer(私有的),一個buffer裏有很多node,一個node相當於一個block(回滾塊)。

IMU特性:
IMU顧名思義就是在內存中的undo,現在每次更改data block,Oracle 不用去更改這個undo block(也不會生成相應的redo了),而是把undo信息緩存到IMU裏去了,只有最後commit或者flush IMU時,這些undo 信息纔會批量更新到undo block,並生成redo。可以避免Undo信息以前在Buffer Cache中的讀寫操作,從而可以進一步的減少Redo生成,同時可以大大減少以前的UNDO SEGMENT的操作。IMU中數據通過暫存、整理與收縮之後也可以寫出到回滾段,這樣的寫出提供了有序、批量寫的性能提升。

IMU主要作用:
減少CR塊-->在構造CR block時,不用像以前那樣從undo block中獲取undo record了,而是用共享池私有IMU區域裏的信息來構造cr block,減少了BUFFER CACEH中 CBC LATCH競爭。
減少REDO日誌條目數-->不再是每條DML語句一個redo records,而是每個事務一個redo records--REDO RECORD的產生會傳到 LOG BUFFER,,會申請LATCH。
減少LATCH-->首先因爲減少REDO RECORD數目;其次用一個IMU latch 代替 redo allocation latch 和 redo copy latch這兩個,也減少了LATCH爭用.
查詢系統中IMU LATCH的數量--也就是Private redo strand area的個數。

IMU 私有REDO區對應的內部表:x$kcrfstrand       IMU UNDO區對應的內部表:x$ktifp
[email protected] bys3>select count(name) from v$latch_children where lower(name) like 'in mem%';
COUNT(NAME)
-----------
         84
[email protected] bys3>select count(*),name from v$latch_children where lower(name) like 'in mem%' group by name;
  COUNT(*) NAME
---------- ----------------------------------------------------------------
        84 In memory undo latch
下面語句可以查詢IMU LATCH的獲取情況
select name,gets from v$latch_children where lower(name) like 'in mem%';

2.在哪些場景下不會使用IMU特性?(ORACLE 10g出現了IMU,默認開啓IMU)
在RAC環境中不支持IMU。
開啓FLASHBACK DATABASE時會開啓打開輔助日誌,此時不能用IMU。
事務過大--據說每個IMU Buffer的Private redo strand area大小大概是64KB(64位的Oracle版本是128KB),大事務不能用。比如一個事務,先有一條UPDATE,此時將REDO私有區域使用完了,此事務的其它DML語句,將自動使用非IMU模式。
共享池太小時,ORACLE會自動不使用IMU。
無法獲取IMU LATCH時,將自動使用非IMU模式。


3.如何手動關閉和開啓IMU模式?

10G和11G中默認是開啓IMU特性的,開啓關閉語句如下:--修改後最好重啓使之生效,或者至少切換一次REDO日誌。
alter system set "_in_memory_undo"=false;
alter system set "_in_memory_undo"=true;  --關閉IMU後使用此語句改回使用IMU特性。

4、談談一條UPDATE語句從第一步到第九步的整個過程?在IMU模式下對REDO日誌做DUMP分析(上圖所示:IMU模式的REDO格式)。


4、談談一條UPDATE語句從第一步到第九步的整個過程?在IMU模式下對REDO日誌做DUMP分析(上圖所示:IMU模式的REDO格式)。
UPDATE語句從第一步到第九步的對應上圖是:
第一步:將更改的數據存放到PGA  
第二步:將BUFFER CACHE中舊數據拷貝到共享池的私有IMU buffer
第三步:將PGA中修改後的數據存放到private redo   private redo--在IMU中才有。
第四步:修改buffre cache中的數據
做提交操作後:
第五步:從IMU中拷貝修改前值到BUFFER CACHE中構建一個CR塊-----即使未提交時SMON每3秒也會做此工作
第六步:第四步修改修改buffre cache中的數據產生的redo日誌寫入log buffe
第七步:第五步操作構造CR塊,產生的redo日誌寫入 log buffe
第八步:由lgwr寫出log buffer到redo log file
第九步:dbwr 將髒數據寫入data file
5.UPDATE操作DUMP REDO 內容實驗記錄:
INSERT 和DELETE語句的,詳見:點擊打開鏈接
REDO RECORD - Thread:1 RBA: 0x000141.00000027.0010 LEN: 0x031c VLD: 0x0d
SCN: 0x0000.00719188 SUBSCN:  1 01/07/2014 20:27:05
(LWN RBA: 0x000141.00000027.0010 LEN: 0002 NST: 0001 SCN: 0x0000.00719187)
####一個REDO RECORD: RECORD頭+CHANGE VECTOR組成(一個CV就是一個操作)
以上是日誌頭,Thread:1 線程號,RAC時會有1,2等
RBA: 0x000141.00000027.0010 將16進制轉換爲十進制分別是日誌文件號、日誌塊號、在塊上第N字節
VLD: 0x0d日誌類型--IMU模式時是這個;非IMU時是:VLD: 0x05
SCN: 0x0000.00719188 SUBSCN:  1 01/07/2014 20:27:05   ----
[email protected] bys3>select scn_to_timestamp(to_number('719188','xxxxxxxx')) from dual;
SCN_TO_TIMESTAMP(TO_NUMBER('719188','XXXXXXXX'))
---------------------------------------------------------------------------
07-JAN-14 08.27.05.000000000 PM
--是此REDO條目產生時的SCN號,轉爲十進制現轉爲時間戳爲:08.27.05, 插入語句完成是在20:27:00 [email protected] bys3>commit;--  --這個是在插入語句完成5秒後,此SCN與CHANGE#4提交時SCN一致。
(LWN RBA: 0x000141.00000027.0010 LEN: 0002 NST: 0001 SCN: 0x0000.00719187)
括號中SCN: 0x0000.00719187 比上一行:SCN: 0x0000.00719187   少了1個SCN。
####

CHANGE #1 TYP:2 CLS:1 AFN:4 DBA:0x010000fd OBJ:22327 SCN:0x0000.007164a1 SEQ:1 OP:11.5 ENC:0 RBL:0
#####AFN:4,操作是在4號文件做的-dba_data_files.file_id;OBJ:22327--操作的對象的OBJECT_ID。OP:11.5-有的版本是OP:11.19--更新操作
KTB Redo
op: 0x11  ver: 0x01
compat bit: 4 (post-11) padding: 1
op: F  xid:  0x0005.002.00000edc    uba: 0x00c041cd.02ea.01
Block cleanout record, scn:  0x0000.0071917c ver: 0x01 opt: 0x02, entries follow...
  itli: 1  flg: 2  scn: 0x0000.007164a1
KDO Op code: URP row dependencies Disabled   -- --URP=UPDATE ROW PIECE。有時會是:KDO Op code:21 row dependencies Disabled
  xtype: XA flags: 0x00000000  bdba: 0x010000fd  hdba: 0x010000fa
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 8(0x8) flag: 0x2c lock: 2 ckix: 0
ncol: 3 nnew: 1 size: 2   --ncol: 3 nnew: 1  表示操作的表有3個列,操作了一列,size: 2
--列字符長度增加2:database減去chedan---根據多次update並DUMP的日誌來看,這裏的size的值應該是:當前CHANGE中的值減去另一個。。
col  1: [ 8]  64 61 74 61 62 61 73 65   --set dname='database'  --col  1: [ 8],第二列,8個字符
[email protected] bys3>select dump('database',16),dump('dataoracle',16) from dual;
DUMP('DATABASE',16)                   DUMP('DATAORACLE',16)
------------------------------------- --------------------------------------------
Typ=96 Len=8: 64,61,74,61,62,61,73,65 Typ=96 Len=10: 64,61,74,61,6f,72,61,63,6c,65
#########################
CHANGE #2 TYP:0 CLS:25 AFN:3 DBA:0x00c000c0 OBJ:4294967295 SCN:0x0000.00719153 SEQ:1 OP:5.2 ENC:0 RBL:0
ktudh redo: slt: 0x0002 sqn: 0x00000edc flg: 0x000a siz: 164 fbi: 0
            uba: 0x00c041cd.02ea.01    pxid:  0x0000.000.00000000
### #####################事務信息
TYP:0 普通塊 ,CLS:25 class大於16是UNDO塊-遞增。AFN:3 絕對文件號dba_data_files.file_id--是UNDO的文件號
DBA:0x00c000c0 數據塊在內存中地址
OBJ:4294967295 --十進制,轉爲16進制是FFFFFFFF
SCN:0x0000.00719153  轉換爲16進制可與操作時對比
OP:5.2 -> operation code 向UNDO段頭的事務表寫事務信息-事務開始
uba: 0x00c041cd.02ea.01  UNDO塊地址
#######################

CHANGE #3 TYP:0 CLS:1 AFN:4 DBA:0x010000fdOBJ:22327 SCN:0x0000.00719188 SEQ:1OP:11.5 ENC:0 RBL:0
KTB Redo        --同CHANGE #1的解析
op: 0x02  ver: 0x01
compat bit: 4 (post-11) padding: 1
op: C  uba: 0x00c041cd.02ea.02
KDO Op code: URP row dependencies Disabled   ---UNDO ROW PIECE
  xtype: XA flags: 0x00000000  bdba: 0x010000fd  hdba: 0x010000fa
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 9(0x9) flag: 0x2c lock: 2 ckix: 0
ncol: 3 nnew: 1 size: 6
col  1: [10]  64 61 74 61 6f 72 61 63 6c 65   --第2列,10個字符--此次操作的字符數
[email protected] bys3>select dump('database',16),dump('dataoracle',16) from dual;
DUMP('DATABASE',16)                   DUMP('DATAORACLE',16)
------------------------------------- --------------------------------------------
Typ=96 Len=8: 64,61,74,61,62,61,73,65 Typ=96 Len=10: 64,61,74,61,6f,72,61,63,6c,65

###########################
CHANGE #4 TYP:0 CLS:25 AFN:3DBA:0x00c000c0 OBJ:4294967295SCN:0x0000.00719188 SEQ:1 OP:5.4 ENC:0 RBL:0
ktucm redo: slt: 0x0002 sqn: 0x00000edc srt: 0 sta: 9 flg: 0x2 ktucf redo: uba: 0x00c041cd.02ea.02 ext: 15 spc: 7890 fbi: 0
######OP:5.4 表明是提交操作。AFN:3 對應的是UNDO文件,slt: 0x0002  修改了UNDO文件的這個事務槽,uba: 0x00c041cd.02ea.02


CHANGE #5 TYP:1 CLS:26 AFN:3 DBA:0x00c041cd OBJ:4294967295 SCN:0x0000.0071917c SEQ:1 OP:5.1 ENC:0 RBL:0
ktudb redo: siz: 164 spc: 0 flg: 0x000a seq: 0x02ea rec: 0x01
###OP:5.1 --把數據修改前值放到UNDO   --AFN:3 --在UNDO文件裏操作,UNDO文件號是3。。CLS:26 --比CHANGE #2中大1,順序增長哈哈
            xid:  0x0005.002.00000edc
ktubl redo: slt: 2 rci: 0 opc: 11.1 [objn: 22327 objd: 22327 tsn: 4]
Undo type:  Regular undo        Begin trans    Last buffer split:  No
Temp Object:  No
Tablespace Undo:  No
             0x00000000  prev ctl uba: 0x00c041cc.02ea.04
prev ctl max cmt scn:  0x0000.00718dff  prev tx cmt scn:  0x0000.00718e4e
txn start scn:  0x0000.00000000  logon user: 32  prev brb: 12599753  prev bcl: 0 BuExt idx: 0 flg2: 0
KDO undo record:
KTB Redo
op: 0x04  ver: 0x01
compat bit: 4 (post-11) padding: 1
op: L  itl: xid:  0x0009.004.00000ebc uba: 0x00c037d5.0249.08
                      flg: C---    lkc:  0     scn: 0x0000.0070cfea
KDO Op code: URP row dependencies Disabled   -----UNDO ROW PIECE
  xtype: XA flags: 0x00000000  bdba: 0x010000fd  hdba: 0x010000fa
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 8(0x8) flag: 0x2c lock: 0 ckix: 0
ncol: 3 nnew: 1 size: -2    ----列字符長度減少2:chedan 減去database---根據多次update並DUMP的日誌來看,這裏的size的值應該是:當前CHANGE中的值減去另一個
col  1: [ 6]  63 68 65 64 61 6e   ----  原值是chedan,,第二列,6個字符
[email protected] bys3>select dump('chedan',16),dump('test',16) from dual;
DUMP('CHEDAN',16)               DUMP('TEST',16)
------------------------------- -------------------------
Typ=96 Len=6: 63,68,65,64,61,6e Typ=96 Len=4: 74,65,73,74


CHANGE #6 TYP:0 CLS:26 AFN:3 DBA:0x00c041cd OBJ:4294967295 SCN:0x0000.00719188 SEQ:1 OP:5.1ENC:0 RBL:0  --解析同上
ktudb redo: siz: 92 spc: 7984 flg: 0x0022 seq: 0x02ea rec: 0x02
            xid:  0x0005.002.00000edc
ktubu redo: slt: 2 rci: 1 opc: 11.1 objn: 22327 objd: 22327 tsn: 4
Undo type:  Regular undo       Undo type:  Last buffer split:  No
Tablespace Undo:  No
             0x00000000
KDO undo record:
KTB Redo
op: 0x02  ver: 0x01
compat bit: 4 (post-11) padding: 1
op: C  uba: 0x00c041cd.02ea.01
KDO Op code: URP row dependencies Disabled     -----UNDO ROW PIECE
  xtype: XA flags: 0x00000000  bdba: 0x010000fd  hdba: 0x010000fa
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 9(0x9) flag: 0x2c lock: 0 ckix: 0
ncol: 3 nnew: 1 size: -6    -列字符長度減少2:test減去database---根據多次update並DUMP的日誌來看,這裏的size的值應該是:當前CHANGE中的值減去另一個
col  1: [ 4]  74 65 73 74     --此次操作,第二列,4個字符
[email protected] bys3>select dump('chedan',16),dump('test',16) from dual;
DUMP('CHEDAN',16)               DUMP('TEST',16)
------------------------------- -------------------------
Typ=96 Len=6: 63,68,65,64,61,6e Typ=96 Len=4: 74,65,73,74


################################################驗證SMON進程

實驗步驟: --這個實驗思路有錯誤的。不應該是DMUP REDO日誌,因爲當時還沒從log buffe寫入redo log file,可以考慮使用--我還未做。

Event 10500 - Trace SMON Process    跟蹤SMON進程    event = "10500 trace name context forever, level 1"    D
12:12:04 [email protected] bys3>select a.group#,a.sequence#,a.archived,a.status,b.type,b.member from v$log a,v$logfile b where a.group#=b.group#;

    GROUP#  SEQUENCE# ARC STATUS           TYPE    MEMBER
---------- ---------- --- ---------------- ------- ------------------------------
         1        334 NO  CURRENT          ONLINE  /u01/oradata/bys3/redo01.log
         2        332 YES ACTIVE           ONLINE  /u01/oradata/bys3/redo02.log
         3        333 YES ACTIVE           ONLINE  /u01/oradata/bys3/redo03.log
Elapsed: 00:00:00.03
12:12:09 [email protected] bys3>select * from dept;
    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        40 OPERATIONS     BOSTON
        11 database       database
        22 dataoracle     sh
Elapsed: 00:00:00.01
12:12:24 [email protected] bys3>update dept set dname='mysql' where deptno=11;
1 row updated.
Elapsed: 00:00:00.01
12:12:29 [email protected] bys3>   ---UPDATE語句完成的時間是:12:12:29,只做UPDATE語句,不要提交,立刻去DUMP REDO LOGFILE.

另一會話在上一步做操作時來DUMP  :  event = "10500 trace name context forever, level 1"