oracle體系結構梳理---redo和undo解析1

lff1530983327發表於2015-01-26

undo用來幹什麼的? undo表空間 

1.事物回滾:rollback   

2查詢一致性 

3.flash back 

例項的恢復時用到的回滾 ---undo讀的是redo檔案中的undo部分

Redo:是基於安全考慮的,會記錄資料庫的所有變化,主要用來做恢復

insert操作

undo:記錄rowid即可

redo:記錄rowid+value

delete操作

undorowid+value

redorowid

update操作

undo:操作之前的rowid+value

redo:操作之後的rowid+value

20:00 會話1開始了一個長達30分鐘的查詢

20:05 會話2開始了一個update並且提交了,其中的undo資訊儲存900s那麼在20:20時候可以被覆蓋

20:22 會話3update了會話2的那一行,導致會話2中的undo資訊被覆蓋

此時會話1在查詢到會話2update的那一行資料是由於要查的是20:00開始的那一刻的資料,但是其undo又被覆蓋了,此時就會產生ora-01555錯誤:快照過舊

普通資料塊上面要留一個undo地址,如果地址被覆蓋或則更改,假設普通資料快上面的資料被更改,但是還未提交,那麼在查詢普通塊時,

會根據普通資料塊記錄的undo資料塊進行一致讀,但是undo塊被覆蓋,其上沒有指向redo檔案的指標,所以一致讀失敗。


create table t(x varchar2(10),y varchar2(10));

insert into t(x,y) values(1,1);------insert 語句。生成的undo足以使insert消失,生成的redo資訊足以使這個插入再次發生

update t set x=x+1 where x=1;

delete from t where x=2;

select  force_logging from v$database;-----YES

select log_mode from v$database;----archivelog

-----------------------------------------ITL----------------------------

create table testblock1( 

id number

name varchar(4

) ;

插入3條資料然後提交: 

 insert into testblock1 values(1,'a'); 

 insert into testblock1 values(2,'b'); 

insert into testblock1 values(3,'c'); 

 commit

select rowid,dbms_rowid.rowid_relative_fno(rowid) rel_fno,dbms_rowid.rowid_block_number(rowid)   blockno from testblock1; 

alter system dump datafile 4 block 142998

oradebug setmypid

oradebug tracefile_name

SELECT      d.VALUE

            || '/'

            || LOWER (RTRIM (i.INSTANCE, CHR (0)))

            || '_ora_'

             || p.spid

             || '.trc'

                AS "trace_file_name"

     FROM   (SELECT   p.spid

                FROM   v$mystat m, v$session s, v$process p

             WHERE   m.statistic# = 1 AND s.SID = m.SID AND p.addr = s.paddr) p,

            (SELECT   t.INSTANCE

              FROM   v$thread t, v$parameter v

            WHERE   v.NAME = 'thread'

                      AND (v.VALUE = 0 OR t.thread# = TO_NUMBER (v.VALUE))) i,

            (SELECT   VALUE

             FROM   v$parameter

            WHERE   NAME = 'user_dump_dest') d;

  -----Oracle什麼情況下select會產生redo ?

1)快速塊清除或者叫commit cleanout。事務提交的時候,oracle針對記憶體裡的塊 

1)把資料塊ITL  ENTRYflag的標記為

2)設定commit scnScn/Fsc列。有了兩個標記就可以告訴全世界這個事務已經提交。

ITL ENTRY 的Lck標誌和每個資料行頭的lb(鎖定位資訊)並不會清除。

Oracle commit cleanout並不會產生日誌,這個你可能會感到比較奇怪,

修改了塊,但是卻沒產生日誌。其實這個產生日誌的過程在後面的完整的塊清除的時候才做。

也就是我們下一次讀取到這個資料塊的時候。

2)延遲塊清除。事務提交的時候,事務修改的塊已經不在記憶體裡了,

這個時候,Oracle不會再從磁碟把塊讀取到記憶體裡做塊清除,

而是在下一次讀取資料塊的時候,做塊清除的動作。這個塊清除的動作會產生Redo

需要注意直接路徑讀取由於繞過了buffer_cache,讀取過程直接在程式的私有PGA裡來完成,

這個過程也會在程式私有的記憶體裡構造CR塊,雖然這個過程裡也會有延遲塊清除發生,

但是不會產生Redo,而且不會把“髒”資料寫會到磁碟。這意味著,如果這個表一直被直接路徑讀取,

將會有許多的浪費的延遲塊清除發生。11G針對大表的全表掃描,11G前並行掃描都會產生直接路徑的讀取。

但是直接路徑讀取即使遇到了需要做延遲塊清除的塊也不會產生Redo

oracle 11g release 2新增的特性為--延遲段建立

這個時候使用create table 不會分配任何儲存空間,一個區段都不會分配。要延遲到insert發生時才會真正建立段,回滾是,段將持久儲存。

回滾過程中重不涉及重做日誌,只有恢復和歸檔的時候才會讀取重做日誌。重做日誌不是用來讀的,是用來寫的。oracle不會再正常的處理中讀取重做日誌。

ARCH讀檔案時,LGWR能寫到另一個不同的裝置中,就不存在重做日誌競爭。

commit時,重做日誌快取組區就會被重新整理輸出,commit之後資料庫做的操作就是:

為事務生成一個SCN

LGWR將所有餘下的快取重做日誌條目寫入磁碟,並把SCN記錄到線上重做日誌檔案中,這是真正的commit,事務條目會從v$transaction中刪除掉

v$lock記錄的而所有的鎖都會被釋放

如果事務修改的某些塊還在緩衝區中,則會議一種快速的模式訪問並‘清理’

塊清除就是指清除儲存在塊首部的鎖相關的資訊。

ROLLBACK之前,資料庫可能已經完成的工作有:

已經在SGA生成UNDO段和已修改的塊還有對應前兩項的redo日誌。同事也已經取得了全部鎖

select force_logging from v$database;

nologging狀態的資料庫並不是不生成redo資訊,還是會有少量的redo資訊來保護我們的資料字典,在一個archivelog模式下開啟nologging一定要及時備份。

建立一個段或則索引時使用nologging那麼以後再重建這些物件的時候將不會再生成redo資訊。

塊清除在commit時候一般會執行,如果未完成。那麼在select的時候就會出現少量的redo資訊,這將可能導致塊變髒(因為本身並沒有被修改,不髒),也將導致下一個檢查點時將大量的塊寫至磁碟。

OLTP資料庫中一般不用考慮塊清除,因為事務一般都很小,在commit時都會完成相應的塊清除。

但是當你在資料倉儲中,如果載入時候要對資料執行大量的update,那就要把塊清除作為一個考慮物件了,認識到這一點就應該在update之後主動接觸這些資料

日誌競爭問題:commit太過於頻繁,或則由於redo所在的裝置硬體問題。

臨時表:修改臨時表中是的資料是不會記入到redo資訊的,不過,會生成undo,所以臨時表還會為undo資訊生成一部分redo資訊所以:

select 臨時表和普通表產生的redo資訊一個很少,一個很多

update 臨時表和普通表 後者是前者的一半

delete 幾乎相同

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30018455/viewspace-1416050/,如需轉載,請註明出處,否則將追究法律責任。

相關文章