天天看點

Oracle——redo+undo總結

《Oracle------redo》

重做日志檔案(redo log file)對資料庫來說至關重要,他們是資料庫的事務日志;

Oracle資料庫維護着兩類重做日志檔案:線上重做日志檔案(redo)和 歸檔重做日志檔案(archive log),(歸檔重做日志檔案實際上就是已填滿的“舊”線上重做日志檔案的副本)

這兩類重做日志檔案都是用于恢複的:

①:如果資料庫所在主機掉電,導緻執行個體失敗,Oracle會使用線上重做日志将系統恢複到恰好在掉電之前的那個送出點;

②:如果磁盤驅動器出現故障(這是媒體失敗),Oracle會使用歸檔重做日志以及線上重做日志,以及之前的一個備份,将原在此驅動器上的資料恢複到某個時間點;

每個Oracle資料庫都至少有兩個線上重做日志,每個組中至少有一個成員(重做日志檔案),線上重做日志組會以循環的方式使用;

Redo log的日志狀态分為4種:

current:指的是目前日志檔案,該日志檔案是活動的,目前正在被使用的,進行崩潰恢複時,Current日志檔案是必須的;

ACTIVE:是活動的非目前日志,可以已經完成歸檔也可能沒有歸檔,在Crash恢複時會被用到;

inactive:非活動日志,在執行個體恢複時不再需要,但是在媒體恢複時可能會用到,此狀态的日志也可能沒有被歸檔。

unused:該日志從未被寫入,這類日志可能是剛被添加到資料庫或者在resetlogs之後被重置。 

《Oracle----undo》

REDO是為了重新實作你的操作,而UNDO相反,是為了撤銷你做的操作,比如你得一個TRANSACTION執行失敗了或你自己後悔了,則需要用ROLLBACK指令回退到操作之前。復原是在邏輯層面實作而不是實體層面,因為在一個多使用者系統中,資料結構,blocks等都在時時變化,比如我們INSERT一個資料,表的空間不夠,擴充了一個新的EXTENT,我們的資料儲存在這新的EXTENT裡,其它使用者随後也在這EXTENT裡插入了資料,而此時我想ROLLBACK,那麼顯然實體上講這EXTENT撤銷是不可能的,因為這麼做會影響其他使用者的操作。是以,ROLLBACK是邏輯上復原,比如對INSERT來說,那麼ROLLBACK就是DELETE了。 

注意:redo是用于在失敗時恢複事務,undo則用來取消一條語句或一組語句的作用。與redo不同,undo是存儲在資料庫内部一組特殊的段中,稱為undo段

1、insert:

第一條insert into t 語句會同時生成redo和undo,它鎖生成的undo資訊足以使insert小時,而redo資訊則足以讓這個insert再次發生;我們可以看到,塊緩沖區裡面存放着修改完的undo塊、索引塊、和表資料塊,所有的這些塊都被重做日志緩沖區中相應條目所保護;

2、update

update 生成的undo量更大,比insert要大,這是因為由于update需要儲存資料修改前的映像;update語句還放在重做日志緩沖區中;

3、delete:

delete會生成undo,塊被修改,并把redo發送到重做日志緩沖區;

4、commit

當事務送出時,Oracle會把重做日志緩沖區重新整理輸出到磁盤;

注意:

insert生成的undo最少;(因為Oracle隻是記錄了一個rowid)

delete生成的undo最多;(因為Oracle必須把整行的删除前映像記錄到undo段中)

(索引的維護也是很高的,比如要更新有索引的列 那麼會生成好幾倍的undo)

commit的開銷主要來自兩方面:

第一:用戶端與資料庫直接往返通信量将會顯著增大

第二:每次送出,都必須等待redo寫至磁盤(在這種情況下,就會出現log file sync的等待事件)

執行commit時,剩下的工作:

1、為事務生成一個SCN号

2、LGWR将所有未寫入磁盤的重做日志條目寫至磁盤,并把SCN記錄到線上重做日志檔案中;

3、v$lock中會記錄着我們的回話鎖,這些鎖都将被釋放,而排隊等待這些鎖的會話都會被喚醒,進而可以繼續完成他們的工作;

4、如果事務修改的某些塊還在緩沖區緩存中,Oracle就會以一種快速的模式通路并清理;

redo  與 undo 日志的主要差別:

1、undo日志:在恢複時取消未完成事務的影響,忽略已經送出的事務

2、redo日志:忽略未完成的事務,重做已經送出事務的改變。

3、undo日志:先将修改後的資料寫到磁盤——寫commit到磁盤

4、redo日志:先寫commit到磁盤——将修改後的資料寫到磁盤

5、undo日志:要求資料在事務結束後立即寫到磁盤,可能增加磁盤IO數

6、redo日志:要求我們在事務送出和日志記錄重新整理以前将所有修改過的塊保留在緩沖區,可能增加事務需要的平均緩沖區數

《臨時表和redo、undo》

在12C之前:

臨時表的資料塊不會生成redo,是以,臨時表的操作不是可恢複的。不過臨時表會生成undo,而且這個undo會計入日志,是以,臨時表也會生成一些redo;臨時表可以有限制,也可以這麼說:正常表有的一切臨時表都可以有;

臨時表的DML操作,有如下特點:

1、insert會生成很少甚至不生成undo  redo

2、臨時表的update會生成永久表update大約一半的redo

3、delete在臨時表上生成的redo與永久表上生成的redo同樣多;

(臨時表delete會生成很多redo,是以要避免進行delete操作,可以truncate;可以使用臨時表進行insert和select操作)

在12C之後:

從Oracle12C起,我們可以通過設定temp_undo_enabled來将臨時表的undo放在臨時表空間中,由于臨時表空間的任何資料變更都不會生成redo,是以當這個參數設定為TRUE時,任何臨時表上的DML都會生産很少甚至不會産生redo;

(temp_undo_enabled的預設值是FALSE,如果将其改為TRUE的話,那臨時表生成的redo量與12C版本之前是一樣的)

ORA-01555: snapshot too old: -----這個錯誤是非常典型的錯誤:(它算的上是一個安全的錯誤,唯一的影響就是收到這個錯誤的查詢無法繼續處理)

産生這個錯誤的原因:

1、undo段太小,不足以支撐系統上執行的工作

2、程式誇commit擷取資料

3、塊清除

4、commit送出太頻繁

解決的方法參考:

1、适當的設定參數undo_retention(要大于運作時間最長的事務所需的時間),我們可以通過v$undostat 來确定長時查詢的持續時間,另外,請在磁盤上預留足夠的空間,因為為了確定undo_retention,undo段可能也會有所增長;

2、使用手動undo管理時加大或增加更多的undo段,(不建議采用這種方法,強烈建議采用自動undo管理方式)

3、減少查詢的運作時間(調優)。調優sql語句、

4、收集相關對象的統計資訊。

本文轉自一個笨小孩51CTO部落格,原文連結:http://blog.51cto.com/fengfeng688/1934429 ,如需轉載請自行聯系原作者