熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

Oracle的redo和undo的區別

2022-06-13   來源: Oracle 

  redo> undo>datafile insert一條記錄時 表跟undo的信息都會放進 redo 中 在commit 或之前 redo 的信息會放進硬盤上 故障時 redo 便可恢復那些已經commit 了的數據 redo>每次操作都先記錄到redo日志中當出現實例故障(像斷電)導致數據未能更新到數據文件則數據庫重啟時須redo重新把數據更新到數據文件 undo>記錄更改前的一份copy但你系統rollback時把這份copy重新覆蓋到原來的數據 redo>記錄所有操作用於恢復(redo records all the database transaction used for recovery) undo>記錄所有的前印象用於回滾(undo is used to store uncommited data infor used for rollback) redo>已遞交的事務實例恢復時要寫到數據文件去的 undo>未遞交的事務 redo的原因是每次commit時將數據的修改立即寫到online redo中但是並不一定同時將該數據的修改寫到數據文件中因為該數據已經提交但是只存在聯機日志文件中所以在恢復時需要將數據從聯機日志文件中找出來重新應用一下使已經更改數據在數據文件中也改過來!

  undo的原因是在oracle正常運行時為了提高效率加入用戶還沒有commit但是空閒內存不多時會由DBWR進程將髒塊寫入到數據文件中以便騰出寶貴的內存供其它進程使用這就是需要UNDO的原因因為還沒有發出commit語句但是oracle的dbwr進程已經將沒有提交的數據寫到數據文件中去了 undo 也是也是datafile 可能dirty buffer 沒有寫回到磁盤裡面去只有先redo apply 成功了才能保證undo datafile 裡面的東西都是正確的然後才能rollback 做undo的目的是使系統恢復到系統崩潰前(關機前)的狀態再進行redo是保證系統的一致性 不做undo系統就不會知道之前的狀態redo就無從談起 所以instance crash recovery 的時候總是先rollforward 再rollback undo 回退段中的數據是以回退條目方式存儲回退條目=塊信息(在事務中發生改動的塊的編號)+在事務提交前存儲在塊中的數據 在每一個回退段中oracle都為其維護一張事務表 在事務表中記錄著與該回退段中所有回退條目相關的事務編號(事務SCN&回退條目) redo 重做記錄由一組變更向量組成每個變更變量中記錄了事務對數據庫中某個塊所做的修改

  當用戶提交一條commit語句時LGWR進程會立刻將一條提交記錄寫入到重做日志文件中然後再開始寫入與該事務相關的重做信息 #事務提交成功後Oracle將為該事備生成一個系統變更碼(SCN)事務的SCN將同時記錄在它的提交記錄和重做記錄中

  commit 提交事務前完成的工作

  ·在SGA區的回退緩存中生成該事務的回退條目在回退條目中保存有該事務所修改的數據的原始版本

  ·在SGA區的重做日志緩存中生成該事務的重做記錄重做記錄中記載了該事務對數據塊所進行的修改並且還記載了對回退段中的數據塊所進行的修改緩存中的重做記錄有可能在事務提交之前就寫入硬盤中

  ·在SGA區的數據庫緩豐中記錄了事務對數據庫所進行的修改這些修改也有可能在事務提交之前就寫入硬盤中

  提交事務時完成的工作

  ·在為該事務指定的回退段中的內部事務表內記錄下這個事務已經被提交並且生成一個惟一的SCN記錄在內部事務表中用於惟一標識這個事務

  ·LGWR後進進程將SGA區重做日志緩存中的重做記錄寫入聯機重做日志文件在寫入重做日志的同時還將寫入該事務的SCN

  ·Oracle服務進程釋放事務所使用的所有記錄鎖與表鎖

  ·Oracle通知用戶事務提交完成

  ·Oracle將該事務標記為已完成

  rollback 回退事務完成的工作

  ·Oracle通過使用回退段中的回退條目撤銷事務中所有SQL語句對數據庫所做的修改

  ·Oracle服務進程釋放事務所使用的所有鎖

  ·Oracle通知事務回退成功

  ·Oracle將該事務標記為已完成

  舉個例子 insert into a(id) values();(redo) 這條記錄是需要回滾的回滾的語句是delete from a where id = ;(undo) 試想想看如果沒有做insert into a(id) values();(redo) 那麼delete from a where id = ;(undo)這句話就沒有意義了 現在看下正確的恢復: 先insert into a(id) values();(redo) 然後delete from a where id = ;(undo) 系統就回到了原先的狀態沒有這條記錄了


From:http://tw.wingwit.com/Article/program/Oracle/201311/16931.html
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.