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、收集相關對象的統計信息。
本文出自 “笨小孩的dba之路” 博客,請務必保留此出處http://fengfeng688.blog.51cto.com/4896812/1934429
Oracle——redo+undo總結