聲明一下:關於oracle的文章基於boobooke小布老師視頻,在我學習的過程中,每有體會拿來分享,雖然從理解到整理分享很耗時,但我想這樣的學習是扎實的。
Undo是干嘛用的?
在介紹undo之前先說一下另外一個東西 transaction ,翻譯成交易或事務。我們在進行一個事務的過程中需要申請許多資源,一個復雜的事務也需要很多步來完成。那么一個復雜的事務是只有兩個結果,要么成功,要么失敗(相當於從來沒發生過)。
一個很典型的列子,銀行轉賬,其實其需要兩步操作,第一步先將你賬戶上的錢減去,第二步把被轉賬戶的錢加上,(先減后加,出了問題銀行不吃虧。呵呵!)這樣就是一個完整的事務。如果執行了一半,你的錢減了,被轉賬戶的錢沒加上,這個時候事務就要回滾,回滾到原始狀態。也就是在轉賬之前,需要先記錄你和被轉賬戶上的金額。這就樣能保證,一旦事務失敗就回滾到事務的發生之前的狀態。
為那保證一個事務的原始性和完整性,就引這入undo 的概念。Undo就是用來記錄保存事務操作過程中的數據,如果事務發生錯誤,可以之前的數據進行填補。
Undo Segment 還原段:
從來面的視圖,我們就可以很清晰的看出,我們要對表(table)中的一個數據進行修改,在修改之前,先把老的映像(old image)放到undo 上面。然后再在table中放入new image 。假如過程失敗,我們還可以把undo 上的old image 再拿回來放在原先的位置,從而使這件事兒看起來像沒發生過一樣。
Undo segment 是保存在表空間上的。Undo 大小是固定的,既然是固定的也就是有限的。如果保存的記錄非常多,那么它就會被占滿,新記錄的數據會覆蓋掉最早的數據。所以用一個圓形的盤片能更加形象的表示。數據從一個位置開始寫入,當寫滿一圈后,最新的數據就會覆蓋最早寫入的數據。
undo可以做哪些事兒?
Transaction rollback 事務反轉, Transaction recovery 事務恢復。事務反轉與事務恢復的效果是一樣的。事務反轉是人主動去做的,人在操作的過程中反悔了,相當於我在寫文檔時按個ctrl+z 。事務恢復是機器自動完成的,比如在事務進行過程中簡拼突然斷電了,下次重啟服務之后,系統自動回滾。
Read consistency 讀一執行。讀一致性對於多用戶操作是非常重要的。如果你在多人開發中使用過版本控制工具(git\cvs\svn)的話,下面的概念你將很容易理解。
Oracle 讀一致性概念
我知道oracle允許可以由多個用戶對數據庫進行操作,當你執行一個查詢幾百萬條記錄的操作時,這個過程可能需要幾分鍾。在這個過程中其它用戶對你查詢的數據時行了修改。這里就要保證你查詢的結果是被修改之前的。
這里明確一個概念,事務的開始,在我們執行一條(更新、修改、刪除)語句時;事務的結束,必須執行提交動作(執行commit 或 rollback 命令)
我們從上面的流程圖來理解一下oracle是如何保證讀一致性的。
當我們執行一個事務的時候,oracle會分配一個SCN編號,這個編號是遞增的。下一個事務的編號一定比當前事務的編號大。上圖中執行第一個事務分配的編號為10023,在這個事務執行的過程中,另一事務對SCN 編號為10008和10021的數據塊進行了修改。用來替換的數據塊SCN編號為10024 ,而被替換掉的數據塊會被保存到undo 上面。當第一個事務執行到被修改過的數據塊時,發現10024比10023大,這個時候就會到undo segment上找比自己SCN號小的數據塊進行讀,於是發找到了SCN號為10008和10021兩個塊。這樣就有效的保證了讀一致性。
當然,會有一種特殊情況,也就是undo segment 太小,最多放100條數據,可一下子來了120條數據,那么最先寫入的20條數據被最后寫入的20條數據覆蓋。這個時候就會報錯,這也是為什么要對數據據進行調優的原因。
Redo or Undo
什么是Redo
Redo記錄transaction logs,分為online和archived。以恢復為目的。
比如,機器停電,那么在重起之后需要online redo logs去恢復系統到失敗點。
比如,磁盤壞了,需要用archived redo logs和online redo logs區恢復數據。
什么是Undo
Redo 是為了重新實現你的操作,而Undo相反,是為了撤銷你做的操作。Undo更像常使用的ctrl+z ,撤銷到上一步的狀態。而Redo 是也就會記錄undo 的操作。
當我們插入一條數據時,首先這個動作會被記錄到redo log 中,操作也會被記錄到到undo ,undo本身的動作也會做為一條數據被記錄到redo log ,插入一條數據,索引(indexes)會發生變化,索引的變化也會做一條數據被記錄到redo log 。Redo 記錄着一個操作所有相關的信息,這樣才能完整的保證場景的重現。
需要說明的是在上面的圖表中,不管是undo 還是redo都是寫在內存里的,一旦斷電,所有信息將會消失。只有寫到磁盤上的信息才不會因為斷電而消失。是redo log 的信息先寫到磁盤上的,因為它的信息最全面,可以完整的保證場景重現。我們可以通過各種機制控制redo 寫磁盤,比如每隔3秒寫一次,或redo log文件大於1MB寫一次。
如何配置使用undo ?
要想使用undo 首先需要創建undo表空間。我們可以創建多個undo表空間,但只能有一個undo表空間是處於使用狀態。
查看undo配置信息:
SQL> show parameter undo NAME TYPE VALUE ------------------------------------ ---------------------------------------------------- undo_management string AUTO undo_retention integer 900 undo_tablespace string UNDOTBS1
Undo配置參數含義
-DNDO_MANAGEMENT undo的管理模式,分自動和手動
-UNDO_TABLESPACE 當前正在被使用的undo表
-UNDO_RETENTION 規定多長時間內,數據不能被覆蓋。
-----------------------------------------
AUTO 表示undo 為自動管理模式。
900 表示在900秒內,undo上的數據不能被覆蓋。
UNDOTBS1 是當前正在使用的undo表空間。
創建undo表空間,與創建一般的表空間類似,命令如下:
SQL> create undo tablespace myundotbs 2 datafile '/ora10/product/oradata/ora10/myundotbs1.dbf' size 10M; Tablespace created.
查看新創建的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 // 新創建的undo表空間 SQL> show parameter undo 再次查看當前使用的表空間 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 再次查看當前使用的表空間 NAME TYPE VALUE ------------------------------------ ---------------------------------------------------- undo_management string AUTO undo_retention integer 900 undo_tablespace string MYUNDOTBS //已經切換的了undo表空間
刪除undo表空間:
SQL> drop tablespace myundotbs;
Tablespace dropped.
Drop一個undo表空間后,在磁盤上還是存在的,我們需要通過操作系統層面用rm命令將文件刪除。
思考:
表空間的切換、刪除命令非常簡單,但這里我們需要思考一下實際切換場景。當我們執行一個事務時,事務執行了一半還沒有提交,這個時候進行切換undo表空間是否可以成功? 理論上undo表空間正在使用中,是不允許切換的。但實際上undo表空間在使用中是可以切換的,但切換之后立刻刪除,系統會提示錯誤。把事務提交后再刪除,系統依然提示錯誤。這里只有將替換掉的undo表空間切換到使用狀態,再切換到廢棄狀態才能被刪除。上面的情況,有興趣有同學可以驗證一下。
Undo調優
Undo的設置取決於我們實際的生產系統。如何設置undo更合理地為我們工作呢?
Undo表空間的大小:
我們在創建一個undo表空間的使用,就指定了它的大小,這個大小一旦創建是不可變更的。設置過大,是一種浪費,設置過小,例如刪除100萬條記錄,這些刪除的記錄都要臨時存放到undo表空間中,如果undo的大小不能存儲100萬條記錄,那么就會出問題。
Undo數據的存放時間:
也就是undo_retention 參數所對應的時間,undo上有數據存放時間與undo大小的密切關系。存放時間越長,需要的表空間越大。就像理發師的數量與理發師的效率的關系一樣。理發師效率很高,一秒鍾解決一個客戶,那么就不需要太多的理發師傅。
Undo表空間的歷史信息:
如何合理設置undo表空間的大小和存放時間呢?那么就需要參考歷史記錄
這個數據每隔10分鍾采集一次,結束時間減去開始時間,在這段時間內使用了多少個undo數據塊。
計算每秒鍾使用數據塊的多少?
求最大值:
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