undo详解
1.首先了解什么是SCN?
時間換算過來的一個遞增數字;保證了數據的一致性!不用時間省去比較的麻煩所以用scn!
當前scn號和時間的對應關系:
查詢當前scn:
但實際上,Oracle 在內部并不是用數字來存儲SCN的。
在Oracle內部,SCN分為兩部分存儲,分別稱之為scn wrap和scn base。實際上SCN長度為48位,即它其實就是一個48位的整數。只不過可能是由于在早些年通常只能處理32位甚至是16位的數據,所以人為地分成了低32位(scnbase)和高16位(scn wrap)。
為什么不設計成64位,這個或許是覺得48位已經足夠長了并且為了節省兩個字節的空間:)。那么SCN這個48位長的整數,最大就是2^48(2的48次方, 281萬億,281474976710656),很大的一個數字了。
這里有一個重要的公式:
? ?SCN= (SCN_WRAP* 4294967296) + SCN_BAS
根據上面的公式,可以計算出SCN的數據值。
在很多與我們事務相關的記錄中都是記錄SCN WRAP 和 SCN BASE.
sys@WENCHAOD> select START_SCNB,START_SCNW from v$transaction;START_SCNB START_SCNW ---------- ----------0 0sys@WENCHAOD> desc smon_scn_time;Name Null? Type----------------------------------------------------- -------- ------------------------------------THREAD NUMBERTIME_MP NUMBERTIME_DP DATESCN_WRP NUMBERSCN_BAS NUMBERNUM_MAPPINGS NUMBERTIM_SCN_MAP RAW(1200)SCN NUMBERORIG_THREAD NUMBERsys@WENCHAOD>控制文件中針對每一個dbf文件有一個scn號(fscn)和一個結束scn(escn )號,在dbf文件頭部有個start scn號 ?---->為了保證文件的一致性!
開始時fscn=start scn,end scn為空!
--數據文件頭部scn號(其實和上面的scn應該相等,但是我查的時候不一樣)
sys@WENCHAOD> select name ,checkpoint_change# from v$datafile_header;NAME ---------------------------------------------------------------------------------------------------- CHECKPOINT_CHANGE# ------------------ /u01/app/oracle/oradata/wenchaodb/system01.dbf1394461/u01/app/oracle/oradata/wenchaodb/sysaux01.dbf1394461/u01/app/oracle/oradata/wenchaodb/undotbs01.dbf1394461/u01/app/oracle/oradata/wenchaodb/users01.dbf1394461/u01/app/oracle/oradata/wenchaodb/example01.dbf1394461sys@WENCHAOD>數據庫正常關閉時,buffer cache寫到磁盤上,同時更新系統scn,fscn,start scn,用關閉的時間點去更新!同時將escn設為和其他的一樣,,即正常關閉后四個scn一樣
非正常關閉,escn為空----->需要實例恢復,,,,其他三個一樣,,
1.需要redo log部分,不要歸檔log
如果把其中一個文件刪除,換了一個備份文件,Oracle啟動時發現scn不一致,使用日志去跑成一樣
跑日志:---------->提升scn:----->需要歸檔日志和redo合起來泡成新的
全部換成是舊的會怎么樣??
備份的時候,控制文件,數據文件,日志文件全部備份了------------------->不會跑日志
日志文件scn
每條日志都有scn
每個日志文件都有兩個scn ?:firsr scn ,next scn;
下一個first就是上一個日志的next;;;可以看作first是該日志文件的第一條日志的scn號,next認為是最后一條scn!!!!
數據庫正常期間:
current日志的first scn ?====數據文件的scn ?===比如1234567
數據庫突然崩了,需要1234567后的日志去恢復,而他的日志在current里面,所有只需要current日志!!!
alter system switch_logfile ?---執行兩次(切換時系統及數據文件scn號不改變,他們主要的作用是表示文件的新舊程度和一致程度)
需要三個日志恢復 ? --------記住:需要幾個根據first scn號和(系統scn號或者是數據文件scn號比較)
日志文件的三種狀態:
inactive:buffer cache 數據已寫回磁盤active:日志文件的日志所對應的臟緩沖區還沒有寫回去(磁盤),日志不能被覆蓋 ?current:log buffer正在使用中file csn ,數據文件頭部scn,系統scn===日志文件current或者是active ? scn號
注意:如果等于current的話,其他兩個一定是inactive狀態
文件 系統的scn====最老的active的scn
跑日志的時候(實例恢復)先定位到日志文件(根據文件、系統、數據文件頭部的scn),再根據control文件中記錄的LRBA定位到具體的日志條目!
所以檢查點進程發生的時候沒有更新 文件、系統、數據文件頭部的scn
總結一下:
檢查點進程發生的時候沒有更新 文件、系統、數據文件頭部的scn,只有當日志文件從active變為inactive時才會更新,end scn只有當數據庫關閉的時候才會更新
以往的first ,next
2.什么是檢查點隊列
buffer cache ,里面單獨有塊區域存放鏈(chain),把buffer鏈起來!LRU,,LRUW(臟塊的訪問頻率,冷端,熱端),CBC。(Google)。。,,為了組織管理小buffer !還有一種鏈叫檢查點隊列鏈,check point chain(按照塊第一次臟的時間)!該鏈上,臟塊!
CKPT兩種工作方式:
1:完全檢查點:ckpt觸發dbwr將所有的臟塊寫到磁盤上!!!!關閉數據庫時觸發
2:增量檢查點:ckpt將檢查點隊列鏈上的第一塊的LRBA地址記錄到控制文件中!!!!每隔3秒觸發!!如果發現臟塊太多,IO不是很忙,結合這兩個因素觸發dbwr,縮短chain!
select cpdrt,cplrba_seq||'.'||cplrba_bno||'.'||cplrba_bof ?"low RBA",cpodr_seq||'.'||cpodr_bno||'.'||cpodr_bof "on disk RBA",cpods,cpodt,cphbt from x$kcccp ;
--cpdrt:檢查點隊列中臟塊的數目
--cpods:on disk rba的scn
--cpodt:on disk rba的時間戳
--cphbt:心跳
sys@WENCHAOD> alter system flush buffer_cache; --清除所有臟塊
3.實例恢復
服務器突然掉電,buffer cache中的臟塊沒有寫到磁盤上,出現數據丟失:1:可以丟失的2:不能丟失的那些可以丟失:沒提交的事務所修改的數據塊可以丟失不可以丟失:已提交的事務所修改的數據塊不可以丟失情況一:事務已經提交但是還沒有寫到磁盤上去?(丟失不能接受)---->通過日志找回(前滾)情況二:事務還沒有提交?(可以接受)如何通過日志找回?一部分在buffer日志中,一部分寫到磁盤上了在buffer中說明事務還沒有提交,如果提交了,他就一定寫到磁盤上了(commit觸發)!數據庫重啟動時,自動發現數據庫非正常關閉,做實例崩潰恢復,使用Oracle磁盤上的日志(redo log)將數據庫崩潰瞬間構造出臟塊,回到出事瞬間!到底是用那些日志恢復呢?終點:on disk rba (current日志文件的最后一條日志)起點:崩潰之前 check point chain上第一塊的LRBA地址,記住,如前面解析,該地址已經記錄到控制文件中 但是,有可能把未提交的事務構造出來,對所有未提交的事務(Oracle在undo中已經記錄了)進行回滾!見后面解析!!!!!!
4.事務,回滾詳解
數據塊有scn,日志有scn!!!日志多了 --->空跑日志事務開始:
一組DML語句:insert delete ?update第一條事務結束:commitrollback假設:執行5條DML語句,修改了8個塊,6個塊對應的日志寫入redo log中,2個在log buffer中------》db崩了------------》重啟Oracle跑日志(LRBA到on disk rba)--------->六個塊被構造出來----------------》事務依賴的會話已死,會話不可能重新完成----------》事務只能被回滾--------》六個塊所做的修改自動被rollback事務是保證數據一致性的一個手段!!事物的隔離級別:默認:set transaction isolation level read ?commit;一個事務提交以前,別的會話看不到未提交的數據的,提交后可以serializable級別:都沒有undo表空間
三個作用:1:讀一致性,構造cr塊2:回滾3:實例恢復undo表空間自動生成,自動有了一堆undo段,段是自動使用的,不需要認為創建!從某種意義來講,只有保證undo表空間的空間大小就可以了,不需要關注undo段如何需要,但是高級dba是要掌握的,解決Oracle性能問題sys@WENCHAOD> show parameter undo_tableNAME TYPE VALUE ------------------------------------ ----------- ------------------------------ undo_tablespace string UNDOTBS1 sys@WENCHAOD> undo表空間占用空間情況以及數據文件存放位置sys@WENCHAOD> select file_name,bytes/1024/1024 from dba_data_files where tablespace_name like '%UNDO%';FILE_NAME ---------------------------------------------------------------------------------------------------- BYTES/1024/1024 --------------- /u01/app/oracle/oradata/wenchaodb/undotbs01.dbf90sys@WENCHAOD>
undo段:sys@WENCHAOD> select * from v$rollname;USN NAME ---------- ------------------------------0 SYSTEM1 _SYSSMU1_3780397527$2 _SYSSMU2_2232571081$3 _SYSSMU3_2097677531$4 _SYSSMU4_1152005954$5 _SYSSMU5_1527469038$6 _SYSSMU6_2443381498$7 _SYSSMU7_3286610060$8 _SYSSMU8_2012382730$9 _SYSSMU9_1424341975$10 _SYSSMU10_3550978943$11 rows selected.sys@WENCHAOD>
1到10在undo表空間里面,0 在系統表空間里面!!睡著事務的增加,undo中自動調整 只有在Oracle對數據字典操作的時候才需要使用system回滾段!!!!比如說建表,對數據庫的對象進行增加刪除的時候才會用到!!undo壞了也會使用system段!!!!!查詢某個段的使用情況select ?segment_name , blocks,extents from dba_segments where segment_name like '%SYSSMU%';占用了哪些區?
9i以前undo自動管理,但是區需要手動分配!!!!9i開始全自動,只要undo表空間容量夠!!sys@WENCHAOD> show parameter undoNAME TYPE VALUE ------------------------------------ ----------- ------------------------------ undo_management string AUTO undo_retention integer 900 undo_tablespace string UNDOTBS1 sys@WENCHAOD>
undo作用,如何使用?undo表空間該設多大??
作用:開始一個事務的時候需要用到!比如delete,Oracle把修改前的數據放到undo表空間的undo段(自動隨機)中!-------回滾!!!!修改的數據越多,undo使用的越多! ? ?讀一致性,構造(cr塊)!實例崩潰恢復中的回滾根本原因:保存了修改前的數據!!!!!undo段中區的狀態free ? ? ? ? ?-----------------------沒有使用expired ? ?--------------------- ?事務提交后,Oracle希望再保存一段時間(undo_retention時間),可以覆蓋inactive ? ---------------------事務提交后,不可以覆蓋(undo_retention時間后),但是如果undo空間壓力大時,也可以覆蓋!但是如果一定想要保存那段時間,修改表空間狀態為guaranteealte tablespace undotbs1 retentionguarantee/noguarantee ? ? ? (desc dba_tablespace)active ? ? ?--------------事務使用段,未提交查詢undo段select usn,xacts,rssize/1024/1024/1024,hwmsize/1024/1024/1024,shrinks from v$rollstat order by rssize;sys@WENCHAOD> select usn,xacts,rssize/1024/1024/1024,hwmsize/1024/1024/1024,shrinks from v$rollstat order by rssize;USN XACTS RSSIZE/1024/1024/1024 HWMSIZE/1024/1024/1024 SHRINKS ---------- ---------- --------------------- ---------------------- ----------0 0 .000358582 .000358582 01 0 .001091003 .002067566 15 0 .001091003 .002067566 29 0 .001091003 .004997253 16 0 .001091003 .002067566 110 0 .001091003 .003044128 18 0 .002067566 .023551941 67 0 .002067566 .003044128 14 0 .002067566 .005973816 23 0 .002067566 .002067566 12 0 .002067566 .002128601 111 rows selected.sys@WENCHAOD> 顯示undo區的狀態信息select extent_id,bytes,status from dba_undo_extents where segment_name like ?'%SYSSMU%';sys@WENCHAOD> select extent_id,bytes,status from dba_undo_extents where segment_name like '%SYSSMU%';EXTENT_ID BYTES STATUS ---------- ---------- ---------0 65536 EXPIRED1 65536 EXPIRED2 1048576 UNEXPIRED0 65536 EXPIRED1 65536 EXPIRED2 1048576 EXPIRED3 1048576 UNEXPIRED0 65536 EXPIRED1 65536 EXPIRED2 1048576 UNEXPIRED3 1048576 EXPIRED0 65536 EXPIRED1 65536 EXPIRED2 1048576 UNEXPIRED3 1048576 EXPIRED0 65536 EXPIRED1 65536 EXPIRED2 1048576 UNEXPIRED0 65536 EXPIRED1 65536 EXPIRED2 1048576 UNEXPIRED0 65536 EXPIRED1 65536 EXPIRED2 1048576 UNEXPIRED3 1048576 EXPIRED0 65536 EXPIRED1 65536 EXPIRED2 1048576 EXPIRED3 1048576 UNEXPIRED0 65536 EXPIRED1 65536 EXPIRED2 1048576 UNEXPIRED0 65536 EXPIRED1 65536 EXPIRED2 1048576 UNEXPIRED35 rows selected.sys@WENCHAOD>圖解一個事務的操作流程
事務開始---->oracle分配事務ID(XID)----->在undo表空間中找一個undo段,在undo段的段頭塊(第一個數據塊)里面有一個事務表(每一個回滾段最多47個事務),找其中一行寫上事務信息(xid:UBA undo塊地址)------------->同時給事務分配undo塊---->將undo塊的地址寫到事務表中---->---->修改數據塊前,首先在事務槽中寫上(XID:UBA)----->將修改前數據保存到undo塊中一個undo段最多可以有47個活動事務,Oracle盡量的一個事務使用一個回滾段,盡量分布均勻!!!!XID即是事務id也是事務地址!(XID:那個回滾段的段頭塊,事務表哪行,該行第幾次被使用)---->唯一標識事務表哪行?假設沒有第三個,事務id可能一樣數據塊的塊頭有事務槽(ITL),在事務修改數據塊(可能修改了很多塊)的時候,在數據塊的頭部(255)寫上事務信息總結:事務開始,在兩個位置寫上事務信息,1,事務表;2,事務槽!為什么?---Oracle事務的提交方式
dump到$Oracle_base/admin/$SID/udump/$spid中
回滾塊:存放修改前的數據!uba指向最新的回滾塊,回滾時根據事務表uba找到最新的, 數據塊直接指向undo是為了在讀一致性是構造CR塊時很方便的構造出來
數據塊事務槽xid指向事務表:為了Oracle的一種提交方式,稍后解析!!!!
轉載于:https://blog.51cto.com/fuwenchao/1376961
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
- 上一篇: 学习:erlang开源项目。
- 下一篇: ASP.NET MVC 学习6、学习使用