一 redo log
Oracle數據庫中的三大核心文件分別是數據文件(data file)、重做日志(redo log)和控制文件(control file)。數據文件保證了數據庫的持久性,是保存修改結果的地方;重做日志保證了數據庫的可恢復性,是保存修改操作(包括對數據文件、控制文件等各類文件的修改)的地方;控制文件的作用是確定數據數據文件和重做日志文件的路徑、數據庫字符集、數據庫當前的狀態、檢查點信息、保存其他文件頭部的部分信息及提供備份信息資料庫等。
重做日志可分為在線重做日志(online redo log)和歸檔重做日志(archive redo log),涉及的5個概念
--RBA(redo byte address)重做字節地址
--SCN(system change number)系統變更號
--DBA(相對數據塊地址)
--數據塊版本號(SCN+SEQ)
--檢查點(checkpoint)
1 Redo record重做記錄
重做日志是數據庫的日記,記錄着每一個對數據庫的更改。日志中所記載的數據稱為重做記錄(redo record),是它提供了數據庫具備了恢復能力。
只要對數據庫做出任何形式的更改,就會在真正執行更改操作之前產生一條重做記錄,該記錄包含了一個或多個操作,記載了數據庫如何從一個狀態改變到另外一個狀態的具體步驟,
往往包含對多個數據塊的修改,也可能包含對控制文件和其他文件的修改。創建表、創建用戶、插入數據、更新、刪除數據,修改表空間屬性、創建表空間、添加數據文件等任何變更都屬於數據塊狀態的更改。
數據庫狀態的變更與事務兩個概念不同。
SCN是內核產生的一個數,兩部分6個字節組成。在正常工作的情況下,oracle不停地按照不同的頻率將SCN寫入不同的文件,在數據庫關閉之后不擔心丟失SCN的進度。判斷數據文件是否需要恢復的指標就是SCN。
v$database視圖的信息大部分來自控制文件,current_scn可以得到一個最新的SCN
select current_scn from v$database
union all
select current_scn from v$database;
select current_scn from v$database
union all
select dbms_flashback.get_system_change_number from dual;
每個能夠修改數據庫狀態的操作,都會將從內核申請到的SCN標記在該操作對應的重做記錄,這樣兩條重做記錄之間就可以分清在時間順序上其對應的操作,scn在文件中的表示
scn: 0x0000.0012fc0a
不能排除多個重做記錄的SCN一樣的情況,這說明有一個以上的修改操作分配到同樣的SCN,由某些oracle內部操作導致的,所以oracle又創建了SUBSCN,用以標記同一個SCN下的多次變更,該值范圍1~254,比如
scn: 0x0000.0012fc0a subscn:1 ,scn: 0x0000.0012fc0a subscn:2 分別表示同一個SCN的先后兩個操作。
修改完成,SCN和SUBSCN會被保存在修改的數據塊的頭部,占7個字節。SUBSCN改稱為SEQ(序列號)。這就是數據塊版本號(SCN+SEQ),經常scn: 0x0000.0012fc0a seq:n形式出現在轉儲文件中。
如此一來,修改操作的SCN就出現在:重做日志和數據文件中。
RBA(重做字節地址),即重做記錄的物理地址,4部分組成:日志線程號、日志序列號、日志文件塊編號和日志文件塊字節偏移量,長度為10個字節。
low cache rba:(0x6a.2650.0) on disk rba:(0x6a.266c.0)
查看
SYS@ orcl >select rowid,empno,job,ename from SCOTT.EMP where empno=7566; ROWID EMPNO JOB ENAME ------------------ ---------- --------- ---------- AAAVUyAAEAAAACVAAD 7566 MANAGER JONES
ROWID以base64的形式體現,前6位代表段號(AAAVUy),隨后3位代表數據文件號(AAE),接下來6位代表數據塊編號(AAAACV),最后的三位代表行號(AAD)
變更矢量
--AFN:絕對文件編號,對應v$datafile.file#字段
SYS@ orcl >select name from v$datafile where file#=3; NAME -------------------------------------------------------------------------------- /u01/app/oracle/oradata/orcl/undotbs01.dbf
--DBA:相對數據塊地址,包含相對文件編號與數據塊編號,4個字節。
---dbms_utility.data_block_address_file()
--SCN和SEQ:數據塊當前的(被修改之前的)的版本號
第一個矢量負責創建事務表,而第二個矢量負責在事務表中創建具體的撤銷數據。
日志緩沖(log buffer)是重做記錄在內存中的臨時保存點,大小由參數
SYS@ orcl >show parameter log_buffer NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ log_buffer integer 6479872
重做記錄進入日志緩沖之后由后台進程LGWR將其寫入在線重做日志,只要符合下面其中一個條件,LGWR就會把log buffer中的所有重做記錄推入在線日志中
--1 每隔3秒
--2 日志緩沖內有1MB的日志記錄
--3 日志緩沖1/3寫滿
--4 執行提交(commit)命令
--5 在DBWn進程中將臟數據塊寫入數據文件之前。
2 Online redo log 在線重做日志
在線重做日志是重做記錄在磁盤上的臨時保存點,是數據庫正常打開不可缺少的文件之一,之所以是臨時的,原因是LGWR會不斷的覆蓋在線日志,它的作用是支持實例恢復和介質恢復。
Oracle出於管理性的考慮把重做日志分為:在線日志和歸檔日志
在線日志是數據庫啟動時一定要被打開的文件,而歸檔日志則不必,如果在線日志損壞,db將無法啟動,因為允許被LGWR重寫覆蓋,除非手動修改,其數量和大小都不會變化而歸檔日志不管理,則會越來越多,視圖v$log,v$logfile
SQL>select lg.group#,lg.members,lf.member from v$log lg,v$logfile lf where lg.group#=lf.group# order by group#; 1 1 /u01/app/oracle/oradata/orcl/redo01.log 2 1 /u01/app/oracle/oradata/orcl/redo02.log 3 1 /u01/app/oracle/oradata/orcl/redo03.log
這里有3個日志組,一般建議每組至少2個在線日志互為鏡像備份,不要把同組的日志放在易單點損壞的存儲上,添加日志組成員
--alter database add logfile member '/u01/app/oracle/oradata/orcl/redo11.log' to group 1;
SYS@ orcl >select group#,sequence#,status from v$log; GROUP# SEQUENCE# STATUS ---------- ---------- ---------------- 1 256 INACTIVE 2 257 CURRENT ##正在寫入的日志組 3 255 INACTIVE 觀察日志組的使用情況, SYS@ orcl >alter system switch logfile; System altered. SYS@ orcl >select group#,sequence#,status from v$log; GROUP# SEQUENCE# STATUS ---------- ---------- ---------------- 1 256 INACTIVE 2 257 ACTIVE 3 258 CURRENT
3 Checkpoint 檢查點
數據庫中的任何一個更改操作,ddl、dml會產生兩種不同類型的數據
--重做記錄,其目的是確保數據庫具有可恢復性
--另一種是被修改的數據庫本身(撤銷數據和修改數據),其目的是確保數據庫的持久性
這兩類數據的臨時存儲地點和永久存儲地點均不相同
重做記錄記載了該更改需要修改哪些數據塊及如何更改,重做記錄在日志緩沖區產生由LGWR寫入在線日志,最后在線日志由ARCn歸檔進程備份為歸檔日志。
被修改的數據塊稱為臟塊,產生了臟塊臨時保存區域database buffer cache,這些數據塊根據重做記錄的RBA按順序在一個檢查點的隊列中,由進程DBWn寫入數據文件,數據塊從檢查點中踢出。數據塊內存中的狀態和數據文件中的狀態一致。
DBWn進程的頻率低於LGWR,保證重做記錄先於對應的臟數據塊寫入持久層,所以,令同一個更改產生的重做記錄為R、臟數據塊為D,那么,在LGWR沒有把R寫入在線日志的情況下,
oracle是不允許DBWn把D先行寫入數據文件的,即便是DBWn首先發起請求,也必須等待LGWR先清空日志緩沖。--即數據更改必須先寫online redo log再寫datafile。
這樣數據文件的內存永遠沒有在線日志的內容更新塊,在數據庫打開的情況下,數據文件永遠比在線日志“舊”。
為了標識數據文件舊到什么程度,oracle使用了檢查點,檢查點是一系列操作的集合,其最終目的是將檢查點目標寫入數據文件頭部和控制文件,檢查點目標就是某條重做記錄,以其頭部中的RBA及SCN表示。
參與檢查點的進程主要包括LGWR、DBWn和CKPT,分為完全檢查點和增量檢查點。
發起一次完全檢查點主要步驟:
--1 在日志緩沖中確定當前的重做記錄,提取RBA和SCN作為檢查點的目標
--2 LGWR清空log buffer,將重做記錄寫入online redo log。
--3 DBWn將檢查點目標(RBA與SCN)產生的及檢查點目標之前產生的臟數據塊,按RBA的順序寫入數據文件
--4 最后,CKPT進程將檢查點目標(RBA與SCN)寫入數據文件頭部和控制文件。
這樣,數據文件頭部的檢查點目標(RBA與SCN)能提供一下兩個重要信息:
--1 讀取其中的scn與online redo log中的scn做比較,就可以知道數據文件是否需要恢復,檢查點目標中的scn簡稱檢查點SCN。
--2 如果該數據文件需要恢復,RBA用來表示從哪個日志中那一項重做記錄開始恢復,檢查點目標中的RBA簡稱檢查點RBA.
完全檢查點發生的時機:
--1 執行shutdown,shutdown norma,shutdown immediate,shutdown transaction命令關閉數據庫
--2 執行alter system checkpoint命令
--3 LGWR切換online redo log,不論是因為日志寫滿還是手工執行alter system switch logfile命令
--4 執行部分表空間維護命令,比如alter tablespace test offine|online|begin backup|end backup|read only| read write,但此類完全檢查點並不完整,DBWn僅將特定表空間內的所有臟數據塊寫回到數據文件而已。
完全檢查點高優先級:shutdown(除shutdown abort外)與alter system checkpoint命令發起的就是高優先級的檢查點,檢查點沒有完成,命令不會返回。
SYS@ orcl >alter system checkpoint; System altered. SYS@ orcl >alter system switch logfile; System altered. Tue May 21 14:49:02 2019 Thread 1 advanced to log sequence 259 (LGWR switch) Current log# 1 seq# 259 mem# 0: /u01/app/oracle/oradata/orcl/redo01.log Current log# 1 seq# 259 mem# 1: /u01/app/oracle/oradata/orcl/redo11.log Tue May 21 14:49:02 2019 Archived Log entry 172 added for thread 1 sequence 258 ID 0x5b6f4ecf dest 1: 查看v$datafile_header字段,可以得到最近一次已經完成的完全檢查點SCN SYS@ orcl >select file#,checkpoint_change# from v$datafile_header; FILE# CHECKPOINT_CHANGE# ---------- ------------------ 1 9249678 2 9249678 3 9249678 4 9249678 5 9249678 SYS@ orcl >select file#,checkpoint_change# from v$datafile; FILE# CHECKPOINT_CHANGE# ---------- ------------------ 1 9249678 2 9249678 3 9249678 4 9249678 5 9249678
增量檢查點,發起時機由oracle自動控制,也可以修改FAST_START_MTTR_TARGET初始化參數影響它的頻率,一次增量檢查點主要步驟:
--1 首先確定一條重做記錄(不是當前的),提取RBA和SCN號作為檢查點的目
--2 LGWR情況log buffer,將重做記錄寫入online redo log
--3 DBWn將檢查點目標(RBA與SCN)產生的及檢查點目標之前的臟數據按RBA順序寫入數據文件
--4 CKPT將檢查點目標(RBA與SCN)寫入控制文件--注意這里與完全檢查點,這里只寫了控制文件
增量檢查點會在告警日志中寫
Incremental checkpoint up to RBA [ ],current log tail at RBA [ ]
將初始化參數log_checkpoint_to_alert為true再觀察
增量檢查點的意義:
--1 減少發生完全檢查點時DBWn進程的工作負擔
--2 提高實例恢復的速度。
4 實例恢復
實例是一系列oracle內存結構和進程的總稱,這些結構是訪問數據庫各種文件的方法,沒有它們,數據庫將不能被訪問,所謂啟動數據庫就是指啟動實例。
當通過shutdown (abort除外)關閉數據庫,oracle會先發起一個完全檢查點,此時數據庫不允許任何變更,log buffer被清除,LGWR進程停止,online redo log更新停止,數據庫緩存中的臟數據完全寫入數據文件。
如果實例崩潰(斷點)或者shutdown abort強制關閉數據庫,沒來及完成一次完全檢查點。在下一次啟動數據庫時候,只要控制文件、redo log和數據文件沒有損壞(只是不同步而已),
為了使數據庫能打開,oracle會自動發起稱為實例恢復的操作同步數據文件,會在alert中寫入
Begining crash recover of
...
Completed crash recover at
實例恢復(instance recovery)的定義是在啟動數據庫時發現文件不同步后,自動利用redo log中的重做記錄自動對舊的數據文件進行修復的過程,分前滾和回滾
實例恢復的第一步前滾,將數據文件頭部中的檢查點SCN和當前redo log中最新的重做記錄的SCN做對比,得知該數據文件是否為舊的,如果判斷為舊,即不同步,前滾發起
前滾--讀取數據文件頭部檢查點RBA,將RBA在redo log文件中找到並作為前滾起點,一直利用完redo log中的最后一條記錄為止。已經提交的變更及沒有提交的變更都寫入數據文件
回滾--需要撤銷數據塊,即便數據庫強制停止時,撤銷數據塊沒有及時寫回數據文件(屬於撤銷表空間),自動前滾也會將他們回復出來
--1 startup命令--手動
--2 參數文件打開,實例啟動
--3 控制文件被打開
--4 校驗數據文件和redo log是否同步(控制文件也參與校驗),結果為否
--5 自動前滾
--6 打開數據庫
--7 自動回滾
牢記實例恢復的一個規定:只能使用在線日志(redo log),並且不要忘記LGWR”喜新厭舊”的品性,以循環覆蓋的方式寫redo log。
在線日志redo log三種狀態:current代表lgwr正在寫的日志組,active最近一次完全檢查點 的RBA(SCN)小於該日志中最后一個重做記錄的RBA(SCN),inactive指最近一次完全檢查點的RBA(SCN)大於該日志中最后一個重組記錄的RBA(SCN).
只有inactive的redo log是實例恢復需要的,active和current都是實例恢復所必需的。
如果LGWR的下一個日志狀態時active,那么LGWR進程會掛起,alert日志報checkpoint not complete.oracle會立刻發起一個新的高優先級檢查點,進一步推進BRA(SCN).除非發生介質問題、文件損壞。
如果只是斷點或實例崩潰,在線日志一定和數據文件是連續的。Oracle總能依靠實例恢復能自動回到完整一致的狀態。
通過v$log.status直接了解到假如現在斷點,實例恢復需要哪些日志
select lg.group#,lg.members,lg.status from v$log lg,v$logfile lf where lg.group#=lf.group# order by group#;
根據結果,應該是日志組1,日志組2和3實例恢復不需要。
5 歸檔重做日志
從介質恢復的角度,在線日志就有可能不行,因為介質恢復應對的是數據文件損壞的情況,一旦數據文件損壞,往往第一步操作是從備份中將損壞的文件還原,
文件頭的檢查點scn也就回到備份的時候,如果超過了redo log中的重做記錄范圍,就無法修復,通過視圖觀察到lgwr寫redo log的速度。
SYS@ orcl >select group#,sequence#,status,to_char(first_time,'yyyy-mm-dd hh24:mi:ss') first_time from v$log; GROUP# SEQUENCE# STATUS FIRST_TIME ---------- ---------- ---------------- ------------------- 1 259 CURRENT 2019-05-21 14:49:02 2 257 INACTIVE 2019-05-21 10:00:58 3 258 INACTIVE 2019-05-21 11:16:08
簡單的說,歸檔日志就是redo log的備份,由后台進程ARCn在LGWR覆蓋之前將redo log復制而來。在數據庫打開時不會打開,不允許覆蓋,在沒有維護的情況下數量不斷增加,是重做記錄的永久保存點。主要作用是支持介質恢復和rman在線備份。
開啟歸檔模式,如何開啟歸檔模式這里不做介紹
SYS@ orcl >select log_mode from v$database; LOG_MODE ------------ ARCHIVELOG SYS@ orcl >select group#,sequence#,status,archived from v$log; GROUP# SEQUENCE# STATUS ARC ---------- ---------- ---------------- --- 1 259 CURRENT NO 2 257 INACTIVE YES ##已經歸檔 3 258 INACTIVE YES ##已經歸檔 --shutdown immediate --startup mount --alter database archivelog --alter database open
歸檔日志保存的路徑由參數log_archive_desc_N和db_recovery_file_dest指定,N最大為31,1~10為本地歸檔,其他為遠程歸檔
SYS@ orcl >show parameter log_archive_dest NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ log_archive_dest string log_archive_dest_1 string location=/u01/app/oracle/arch --SQL> alter system set log_archive_dest_1=’location=/u01/app/oracle/arch’; 歸檔文件的格式,該參數一定要包含%t,%s和%r SYS@ orcl >show parameter log_archive_format NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ log_archive_format string %t_%s_%r.db select sequence#,first_change#,next_change#,name from v$archived_log;
6 介質恢復
在文件有物理損壞的情況下,將其還原、恢復,最后使數據庫得以正常打開的操作稱為介質恢復。
實例恢復的前提是數據文件、控制文件和在線日志均沒有損壞的情況
比如,system01.dbf文件損壞
SQL> startup ORACLE instance started. Total System Global Area 784998400 bytes Fixed Size 2257352 bytes Variable Size 511708728 bytes Database Buffers 264241152 bytes Redo Buffers 6791168 bytes Database mounted. ORA-01122: database file 1 failed verification check ORA-01110: data file 1: '/u01/app/oracle/oradata/orcl/system01.dbf' ORA-01210: data file header is media corrupt
#只能啟動到mount階段,提示需要介質恢復
首先查看所有數據文件的檢查點SCN
SYS@ orcl >select file#,name,checkpoint_change# from v$datafile;
凍結1號文件的頭部,oracle會對1號文件發起完全檢查點,屬於1號文件的臟數據塊將全部寫入磁盤
SYS@ orcl >alter tablespace system begin backup; Tablespace altered. SYS@ orcl >col name format a50 SYS@ orcl >select file#,name,checkpoint_change# from v$datafile; FILE# NAME CHECKPOINT_CHANGE# ---------- -------------------------------------------------- ------------------ 1 /u01/app/oracle/oradata/orcl/system01.dbf 9252840 2 /u01/app/oracle/oradata/orcl/sysaux01.dbf 9249773 3 /u01/app/oracle/oradata/orcl/undotbs01.dbf 9249773 4 /u01/app/oracle/oradata/orcl/users01.dbf 9249773 5 /u01/app/oracle/oradata/orcl/test01.dbf 9249773 然后用os命令備份 [oracle@DSI ~]$ cp /u01/app/oracle/oradata/orcl/system01.dbf /home/oracle/systm01.dbf SYS@ orcl >alter tablespace system end backup; ##解凍 Tablespace altered. 然后在把剛備份的system01復制原處,此時alter database open就會報錯,因為scn不一致。 SYS@ orcl >shutdown immediate; [oracle@DSI ~]$ cp /home/oracle/systm01.dbf /u01/app/oracle/oradata/orcl/system01.dbf SYS@ orcl >startup; ORACLE instance started. Total System Global Area 784998400 bytes Fixed Size 2257352 bytes Variable Size 511708728 bytes Database Buffers 264241152 bytes Redo Buffers 6791168 bytes Database mounted. ORA-01113: file 1 needs media recovery ORA-01110: data file 1: '/u01/app/oracle/oradata/orcl/system01.dbf' 查看還原1號文件的scn SYS@ orcl >select file#,change# from v$recover_file; FILE# CHANGE# ---------- ---------- 1 9252840 查看非INACTIVE狀態的redo log的低位SCN SYS@ orcl >select min(first_change#) from v$log where status !='INACTIVE'; MIN(FIRST_CHANGE#) ------------------ 9249773 還原的scn大於非inactive的redo log的低位scn 查看歸檔最小的scn號 SYS@ orcl >select min(first_change#) from v$archived_log; MIN(FIRST_CHANGE#) ------------------ 1121577 這里1121577明顯小於9252840,可以恢復 SYS@ orcl >recover automatic datafile 1; Media recovery complete. SYS@ orcl >alter database open; Database altered. SYS@ orcl >select file#,name,checkpoint_change# from v$datafile; FILE# NAME CHECKPOINT_CHANGE# ---------- -------------------------------------------------- ------------------ 1 /u01/app/oracle/oradata/orcl/system01.dbf 9253054 2 /u01/app/oracle/oradata/orcl/sysaux01.dbf 9253054 3 /u01/app/oracle/oradata/orcl/undotbs01.dbf 9253054 4 /u01/app/oracle/oradata/orcl/users01.dbf 9253054 5 /u01/app/oracle/oradata/orcl/test01.dbf 9253054
介質恢復的步驟
--1 手動還原,數據文件遭到破壞,導致實例恢復這個流程無法進行,所以第一步是將之前備份的數據文件復制到原位置,完整性沒有問題,但是其頭部的檢查點scn與redo log的不連續,實例恢復還是無法進行,此時不能使用alter database open打開
--2 手動恢復,sqlplus的recover命令能夠分析數據文件頭部中的檢查點scn和RBA,了解數據文件是否需要恢復、從哪里開始恢復,並且能夠讀取到歸檔日志和redo log中的重做記錄,將變更重做,把數據文件中丟失的變更重新找回。
--3 自動回滾,在執行alter database open打開數據庫后自動執行
介質恢復需要人為干預的只有兩部分:還原操作(restore)和恢復操作(recover)
SYS@ orcl >alter system dump logfile '/u01/app/oracle/oradata/orcl/redo01.log' dba min 5 319 dba max 5 400; System altered. SYS@ orcl >select value from v$diag_info where name='Default Trace File'; VALUE ----------------------------------------------------------------- /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_10017.trc