Undo是干嘛用的? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
在介紹undo之前先說(shuō)一下另外一個(gè)東西?transaction?,翻譯成交易或事務(wù)。我們?cè)谶M(jìn)行一個(gè)事務(wù)的過(guò)程中需要申請(qǐng)?jiān)S多資源,一個(gè)復(fù)雜的事務(wù)也需要很多步來(lái)完成。那么一個(gè)復(fù)雜的事務(wù)是只有兩個(gè)結(jié)果,要么成功,要么失敗(相當(dāng)于從來(lái)沒(méi)發(fā)生過(guò))。
一個(gè)很典型的列子,銀行轉(zhuǎn)賬,其實(shí)其需要兩步操作,第一步先將你賬戶上的錢減去,第二步把被轉(zhuǎn)賬戶的錢加上,這樣就是一個(gè)完整的事務(wù)。
如果執(zhí)行了一半,你的錢減了,被轉(zhuǎn)賬戶的錢沒(méi)加上,這個(gè)時(shí)候事務(wù)就要回滾,回滾到原始狀態(tài)。也就是在轉(zhuǎn)賬之前,需要先記錄你和被轉(zhuǎn)賬戶上的金額。這就樣能保證,一旦事務(wù)失敗就回滾到事務(wù)的發(fā)生之前的狀態(tài)。
為那保證一個(gè)事務(wù)的原始性和完整性,就引這入undo?的概念。Undo就是用來(lái)記錄保存事務(wù)操作過(guò)程中的數(shù)據(jù),如果事務(wù)發(fā)生錯(cuò)誤,可以之前的數(shù)據(jù)進(jìn)行填補(bǔ)。
Undo?Segment?還原段:
從來(lái)面的視圖,我們就可以很清晰的看出,我們要對(duì)表(table)中的一個(gè)數(shù)據(jù)進(jìn)行修改,在修改之前,先把老的映像(old?image)放到undo?上面。然后再在table中放入new?image?。
假如過(guò)程失敗,我們還可以把undo?上的old?image?再拿回來(lái)放在原先的位置,從而使這件事兒看起來(lái)像沒(méi)發(fā)生過(guò)一樣。
Undo?segment?是保存在表空間上的。Undo?大小是固定的,既然是固定的也就是有限的。如果保存的記錄非常多,那么它就會(huì)被占滿,新記錄的數(shù)據(jù)會(huì)覆蓋掉最早的數(shù)據(jù)。
所以用一個(gè)圓形的盤片能更加形象的表示。數(shù)據(jù)從一個(gè)位置開(kāi)始寫(xiě)入,當(dāng)寫(xiě)滿一圈后,最新的數(shù)據(jù)就會(huì)覆蓋最早寫(xiě)入的數(shù)據(jù)。
undo可以做哪些事兒? ? ? ? ? ? ? ??
Transaction?rollback??事務(wù)反轉(zhuǎn),?Transaction?recovery?事務(wù)恢復(fù)。事務(wù)反轉(zhuǎn)與事務(wù)恢復(fù)的效果是一樣的。事務(wù)反轉(zhuǎn)是人主動(dòng)去做的,人在操作的過(guò)程中反悔了,相當(dāng)于我在寫(xiě)文檔時(shí)按個(gè)ctrl+z?。事務(wù)恢復(fù)是機(jī)器自動(dòng)完成的,比如在事務(wù)進(jìn)行過(guò)程中簡(jiǎn)拼突然斷電了,下次重啟服務(wù)之后,系統(tǒng)自動(dòng)回滾。
Read?consistency??讀一執(zhí)行。讀一致性對(duì)于多用戶操作是非常重要的。如果你在多人開(kāi)發(fā)中使用過(guò)版本控制工具(gitcvssvn)的話,下面的概念你將很容易理解。
oracle?讀一致性概念 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
我知道oracle允許可以由多個(gè)用戶對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作,當(dāng)你執(zhí)行一個(gè)查詢幾百萬(wàn)條記錄的操作時(shí),這個(gè)過(guò)程可能需要幾分鐘。在這個(gè)過(guò)程中其它用戶對(duì)你查詢的數(shù)據(jù)時(shí)行了修改。這里就要保證你查詢的結(jié)果是被修改之前的。
這里明確一個(gè)概念,事務(wù)的開(kāi)始,在我們執(zhí)行一條(更新、修改、刪除)語(yǔ)句時(shí);事務(wù)的結(jié)束,必須執(zhí)行提交動(dòng)作(執(zhí)行commit?或?rollback?命令)
我們從上面的流程圖來(lái)理解一下oracle是如何保證讀一致性的。
當(dāng)我們執(zhí)行一個(gè)事務(wù)的時(shí)候,oracle會(huì)分配一個(gè)SCN編號(hào),這個(gè)編號(hào)是遞增的。下一個(gè)事務(wù)的編號(hào)一定比當(dāng)前事務(wù)的編號(hào)大。
上圖中執(zhí)行第一個(gè)事務(wù)分配的編號(hào)為10023,在這個(gè)事務(wù)執(zhí)行的過(guò)程中,另一事務(wù)對(duì)SCN?編號(hào)為10008和10021的數(shù)據(jù)塊進(jìn)行了修改。用來(lái)替換的數(shù)據(jù)塊SCN編號(hào)為10024?,而被替換掉的數(shù)據(jù)塊會(huì)被保存到undo?上面。
當(dāng)?shù)谝粋€(gè)事務(wù)執(zhí)行到被修改過(guò)的數(shù)據(jù)塊時(shí),發(fā)現(xiàn)10024比10023大,這個(gè)時(shí)候就會(huì)到undo?segment上找比自己SCN號(hào)小的數(shù)據(jù)塊進(jìn)行讀,于是發(fā)找到了SCN號(hào)為10008和10021兩個(gè)塊。這樣就有效的保證了讀一致性。
當(dāng)然,會(huì)有一種特殊情況,也就是undo?segment?太小,最多放100條數(shù)據(jù),可一下子來(lái)了120條數(shù)據(jù),那么最先寫(xiě)入的20條數(shù)據(jù)被最后寫(xiě)入的20條數(shù)據(jù)覆蓋。這個(gè)時(shí)候就會(huì)報(bào)錯(cuò),這也是為什么要對(duì)數(shù)據(jù)據(jù)進(jìn)行調(diào)優(yōu)的原因。
Redo?or Undo? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
什么是Redo
Redo記錄transaction?logs,分為online和archived。以恢復(fù)為目的。
比如,機(jī)器停電,那么在重起之后需要online?redo?logs去恢復(fù)系統(tǒng)到失敗點(diǎn)。
比如,磁盤壞了,需要用archived?redo?logs和online?redo?logs區(qū)恢復(fù)數(shù)據(jù)。
什么是Undo
Redo?是為了重新實(shí)現(xiàn)你的操作,而Undo相反,是為了撤銷你做的操作。Undo更像常使用的ctrl+z?,撤銷到上一步的狀態(tài)。而Redo?是也就會(huì)記錄undo?的操作。
當(dāng)我們插入一條數(shù)據(jù)時(shí),首先這個(gè)動(dòng)作會(huì)被記錄到redo?log?中,操作也會(huì)被記錄到到undo?,undo本身的動(dòng)作也會(huì)做為一條數(shù)據(jù)被記錄到redo?log?,插入一條數(shù)據(jù),索引(indexes)會(huì)發(fā)生變化,索引的變化也會(huì)做一條數(shù)據(jù)被記錄到redo?log?。Redo?記錄著一個(gè)操作所有相關(guān)的信息,這樣才能完整的保證場(chǎng)景的重現(xiàn)。
需要說(shuō)明的是在上面的圖表中,不管是undo?還是redo都是寫(xiě)在內(nèi)存里的,一旦斷電,所有信息將會(huì)消失。只有寫(xiě)到磁盤上的信息才不會(huì)因?yàn)閿嚯姸А?/p>
是redo?log?的信息先寫(xiě)到磁盤上的,因?yàn)樗男畔⒆钊妫梢酝暾谋WC場(chǎng)景重現(xiàn)。我們可以通過(guò)各種機(jī)制控制redo?寫(xiě)磁盤,比如每隔3秒寫(xiě)一次,或redo?log文件大于1MB寫(xiě)一次。
如何配置使用undo?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
要想使用undo?首先需要?jiǎng)?chuàng)建undo表空間。我們可以創(chuàng)建多個(gè)undo表空間,但只能有一個(gè)undo表空間是處于使用狀態(tài)。
查看undo配置信息:
SQL>?show?parameter?undo NAME???????????????????????????TYPE????????????????VALUE ------------------------------------?---------------------------------------------------- undo_management?????????????????string????????????auto??? undo_retention???????????????????integer???????????900 undo_tablespace??????????????????string???????????UNDOTBS1
Undo配置參數(shù)含義
-DNDO_MANAGEMENT? ? ?undo的管理模式,分自動(dòng)和手動(dòng)
-UNDO_TABLESPACE? ? ? 當(dāng)前正在被使用的undo表
-UNDO_RETENTION? ? ? ? 規(guī)定多長(zhǎng)時(shí)間內(nèi),數(shù)據(jù)不能被覆蓋。
AUTO ? ? ? ? ? ??表示undo?為自動(dòng)管理模式。
900 ? ? ? ? ? ? ? 表示在900秒內(nèi),undo上的數(shù)據(jù)不能被覆蓋。
UNDOTBS1????是當(dāng)前正在使用的undo表空間。
創(chuàng)建undo表空間,與創(chuàng)建一般的表空間類似,命令如下:
SQL>?create?undo?tablespace?myundotbs ??2??datafile?'/ora10/product/oradata/ora10/myundotbs1.dbf'?size?10M; Tablespace?created.
查看新創(chuàng)建的undo表空間
SQL>??select?tablespace_name,contents?from?dba_tablespaces; TABLESPACE_NAME????????????????????CONTENTS ------------------------------------------------------------?------------------ SYSTEM?????????????????????????????????PERMANENT UNDOTBS1???????????????????????????????UNDO??? //老的undo表空間 SYSAUX?????????????????????????????????PERMANENT TEMP????????????????????????????????????TEMPORARY USERS??????????????????????????????????PERMANENT PAUL???????????????????????????????????PERMANENT MYUNDOTBS??????????????????????????????UNDO???//?新創(chuàng)建的undo表空間 SQL>?show?parameter?undo??????再次查看當(dāng)前使用的表空間 NAME???????????????????????????TYPE??????????VALUE ------------------------------------?---------------------------------------------------- undo_management?????????????????string????????????AUTO??? undo_retention???????????????????integer?????????????900 undo_tablespace??????????????????string???????????UNDOTBS1
切換undo表空間:
SQL>?alter?system?set?undo_tablespace=myundotbs; System?altered. SQL>?show?parameter?undo???再次查看當(dāng)前使用的表空間 NAME???????????????????????????TYPE???????????????VALUE ------------------------------------?---------------------------------------------------- undo_management?????????????????string????????????AUTO??? undo_retention???????????????????integer??????????900 undo_tablespace??????????????????string???????????MYUNDOTBS????//已經(jīng)切換的了undo表空間
刪除undo表空間:
SQL>?drop?tablespace?myundotbs; Tablespace?dropped.
Drop一個(gè)undo表空間后,在磁盤上還是存在的,我們需要通過(guò)操作系統(tǒng)層面用rm命令將文件刪除。
思考:
表空間的切換、刪除命令非常簡(jiǎn)單,但這里我們需要思考一下實(shí)際切換場(chǎng)景。當(dāng)我們執(zhí)行一個(gè)事務(wù)時(shí),事務(wù)執(zhí)行了一半還沒(méi)有提交,這個(gè)時(shí)候進(jìn)行切換undo表空間是否可以成功??
理論上undo表空間正在使用中,是不允許切換的。但實(shí)際上undo表空間在使用中是可以切換的,但切換之后立刻刪除,系統(tǒng)會(huì)提示錯(cuò)誤。把事務(wù)提交后再刪除,系統(tǒng)依然提示錯(cuò)誤。這里只有將替換掉的undo表空間切換到使用狀態(tài),再切換到廢棄狀態(tài)才能被刪除。
Undo調(diào)優(yōu) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
Undo的設(shè)置取決于我們實(shí)際的生產(chǎn)系統(tǒng)。如何設(shè)置undo更合理地為我們工作呢?
Undo表空間的大小:
我們?cè)趧?chuàng)建一個(gè)undo表空間的使用,就指定了它的大小,這個(gè)大小一旦創(chuàng)建是不可變更的。設(shè)置過(guò)大,是一種浪費(fèi),設(shè)置過(guò)小,例如刪除100萬(wàn)條記錄,這些刪除的記錄都要臨時(shí)存放到undo表空間中,如果undo的大小不能存儲(chǔ)100萬(wàn)條記錄,那么就會(huì)出問(wèn)題。
Undo數(shù)據(jù)的存放時(shí)間:
也就是undo_retention?參數(shù)所對(duì)應(yīng)的時(shí)間,undo上有數(shù)據(jù)存放時(shí)間與undo大小的密切關(guān)系。存放時(shí)間越長(zhǎng),需要的表空間越大。就像理發(fā)師的數(shù)量與理發(fā)師的效率的關(guān)系一樣。理發(fā)師效率很高,一秒鐘解決一個(gè)客戶,那么就不需要太多的理發(fā)師傅。
Undo表空間的歷史信息:
如何合理設(shè)置undo表空間的大小和存放時(shí)間呢?那么就需要參考?xì)v史記錄
這個(gè)數(shù)據(jù)每隔10分鐘采集一次,結(jié)束時(shí)間減去開(kāi)始時(shí)間,在這段時(shí)間內(nèi)使用了多少個(gè)undo數(shù)據(jù)塊。
計(jì)算每秒鐘使用數(shù)據(jù)塊的多少?
求最大值: SQL>?select?max(undoblks?/?((end_time-begin_time)*24*3600))?from?v$undostat; MAX(UNDOBLKS/((END_TIME-BEGIN_TIME)*24*3600)) --------------------------------------------- ???????????????????????????????????14.15833333 求平均值: SQL>??select?sum(undoblks)/sum((end_time?-?begin_time)*24*3600)?from?v$undostat; SUM(UNDOBLKS)/SUM((END_TIME-BEGIN_TIME)*24*3600) ------------------------------------------------ ??????????????????????????????????????4.122282389