境安全實踐指南)
接手一套生產庫的第一件事我基本都會先看兩樣東西備份策略長什么樣歸檔日志使用率到哪了。前兩年排查過一套業(yè)務系統(tǒng)數(shù)據(jù)庫磁盤被歸檔日志撐滿整個實例卡在日志切換上所有寫事務全部阻塞最后是先用 RMAN 清掉一批已經備份過的歸檔日志才讓系統(tǒng)恢復過來。RMAN 備份恢復、刪除歸檔聽起來是 Oracle 日常運維里最常見的操作但在生產環(huán)境里每一步都做對絕對沒那么簡單。這篇文章不打算背命令手冊重點講底層邏輯和實操判斷RMAN 的數(shù)據(jù)塊備份機制是怎么回事歸檔日志在恢復鏈路里扮演什么角色全備、增量、歸檔之間如何搭配怎樣安全地把歸檔日志清掉以及真遇到數(shù)據(jù)文件損壞時怎么把數(shù)據(jù)庫完整撈回來。我會把常用命令、參數(shù)設計思路和踩過的坑一起放出來希望對你手頭的備份方案有實際參考價值。1. 先理解 RMAN 的備份體系與歸檔日志機制1.1 RMAN 和普通文件備份到底有什么區(qū)別很多剛接觸 Oracle 的運維人員最先想到的備份方式是用 cp 或 tar 直接拷貝數(shù)據(jù)文件這種叫用戶管理備份。它看起來直觀實際上問題不少。第一它會備份全部內容無論數(shù)據(jù)文件里有沒有實際數(shù)據(jù)空閑塊也被拷貝一遍浪費存儲和時間。第二數(shù)據(jù)庫運行時數(shù)據(jù)文件本身處于不一致狀態(tài)因為 buffer cache 里的臟數(shù)據(jù)還沒刷到文件redo log 也在不斷變化。直接拷貝出來的文件要在恢復時可能需要你自己去處理一大堆一致性校驗工作稍不留神就恢復失敗。RMAN 的邏輯完全不一樣。它通過服務器會話讀取數(shù)據(jù)塊找到 allocated block 也就是真正有數(shù)據(jù)的塊只備份這些塊并在備份過程中做數(shù)據(jù)塊內部的邏輯校驗。它生成的是自包含的備份集里面還會記錄必要的元數(shù)據(jù)包含 SCN、數(shù)據(jù)文件號等等?;謴蜁r RMAN 知道該用哪個備份片也知道備份和當前 redo log 的 sequence 之間差多少從而自動完成恢復動作。打個比方手動備份就像把一屋子文件全部復印了一遍塞進倉庫備份了多少東西全靠自己心里記RMAN 更像一套帶索引的檔案管理系統(tǒng)它不光告訴你文件在哪還記錄什么時間點有什么版本你只需要告訴它“恢復到某個時間”它就能自己按目錄找文件、按順序歸檔重做日志。這也是為什么在數(shù)據(jù)量不小且要求可恢復性的核心庫上大家普遍選擇 RMAN。1.2 歸檔日志為什么是恢復的生命線Oracle 的數(shù)據(jù)庫修改流程是先寫重做日志再寫數(shù)據(jù)文件。聯(lián)機重做日志是循環(huán)覆蓋的一組寫滿之后切換下一組。如果數(shù)據(jù)庫是非歸檔模式切換出去的那組日志一旦被覆蓋舊內容就永久消失數(shù)據(jù)庫也就只能恢復到最近一次檢查點附近。如果數(shù)據(jù)庫開啟了歸檔模式ARCHIVELOG日志切換時后臺進程會把即將被覆蓋的日志內容復制為歸檔日志文件等于是給每個歷史 redo 日志留下了一份完整副本。有了這份副本數(shù)據(jù)庫才能實現(xiàn)介質恢復。比如周三數(shù)據(jù)文件所在的磁盤壞了而你的全備是周日晚上做的那么周日晚到周三損壞時刻之間的所有變更只能靠歸檔日志和當前在線 redo log 來重放?;謴筒襟E就是先把全備的物理文件恢復出來再把備份后的歸檔日志從早到晚重新應用數(shù)據(jù)庫最終推進到接近故障點的狀態(tài)。這也回答了一個常見問題為什么不能隨意刪除歸檔日志。刪早了刪多了恢復窗口就會縮短遇到故障你可能只能恢復到更早的備份點數(shù)據(jù)丟失量會成倍放大。所以歸檔日志不是“越刪越爽”的日志殘留它的存在本身就是 RPO恢復點目標的兜底。理解了這一點再去討論刪除歸檔的操作你才會明白為什么要把“是否有備份”“是否在保留策略范圍內”放在刪除之前先想清楚。2. RMAN 備份實操從環(huán)境準備到備份命令2.1 確認數(shù)據(jù)庫開啟歸檔模式在寫備份腳本之前必須先確認數(shù)據(jù)庫處于歸檔模式。用 SQL 執(zhí)行這條命令就可以SQL archive log list; Database log mode Archive Mode Automatic archival Enabled Archive destination USE_DB_RECOVERY_FILE_DEST Oldest online log sequence 1024 Next log sequence to archive 1031 Current log sequence 1031如果看到 No Archive Mode需要按下面步驟把數(shù)據(jù)庫切成歸檔模式。整個過程要重啟一次實例建議放在業(yè)務低峰或維護窗口進行SQL shutdown immediate; SQL startup mount; SQL alter database archivelog; SQL alter database open;注意開啟歸檔模式之后數(shù)據(jù)庫會產生歸檔日志文件。如果你的歸檔目錄是快速恢復區(qū)Fast Recovery AreaFRA那么 FRA 的空間規(guī)劃直接影響能容納多少歸檔文件。很多生產庫走到“刪除歸檔”這一步其實就是因為最初 FRA 給得太小備份全占了空間歸檔一兩周就把磁盤填滿了。所以補課的第一步不只是會切換歸檔還要心里有數(shù)這個庫每小時/每天能產生多少歸檔空間能撐多久。2.2 全備腳本最基礎也最剛需的命令先給出一份我實際用來做每日全備的最小腳本它對中小型生產庫基本夠用RMAN run { allocate channel c1 device type disk format /backup/rman/%U; backup database plus archivelog delete input; backup current controlfile; backup spfile; release channel c1; }這里最值得關注的是backup database plus archivelog delete input。它的執(zhí)行順序比較巧妙在備份數(shù)據(jù)文件之前先把當前已經生成的歸檔日志備份進備份集然后開始備份數(shù)據(jù)文件數(shù)據(jù)文件備份完成后再備份這段時間里新生成的歸檔日志。也就是說從備份開始到結束所有歸檔日志都有備份沒有遺漏窗口。delete input則在成功備份這些歸檔日志后把原始歸檔文件從磁盤刪除。所以它本質上是“先備份后清理”這也是刪除歸檔最安全的一種姿勢比單獨執(zhí)行delete archivelog all要穩(wěn)得多。有人會問這份腳本里為什么要單獨寫backup current controlfile和backup spfileRMAN 在backup database時默認也會備份控制文件和參數(shù)文件但我習慣顯式寫出來。第一恢復時可以直接引用控制文件備份避免依賴自動行為第二腳本的可讀性更好換人接手時一看就明白庫的骨架文件有沒有被覆蓋。多寫兩行幾乎不增加成本卻能讓后續(xù)的恢復過程清晰很多。2.3 增量備份、通道配置與備份集校驗數(shù)據(jù)量超過幾十 GB 后每天全備可能不現(xiàn)實備份窗口會被拉得很長。增量備份是更務實的選擇。RMAN 的增量備份分 0 級和 1 級。0 級會備份一個基線是后續(xù)增量恢復的起點1 級只備份自上次備份以來發(fā)生變化的 block。差異式 1 級備份體積可能更小但恢復時需要讀取上一次 1 級備份及 0 級基線累積式 1 級備份備份自 0 級以來所有變化的塊體積更大一些但恢復時要應用的文件更少恢復速度更快。一個常用方案是周日凌晨做 0 級周一到周六做 1 級差異式或累積式同時每次都帶上plus archivelog delete input。如果業(yè)務變化集中、恢復要求高可以把 0 級頻率提高到一天一次或兩天一次。增量級別并不需要設置得多復雜關鍵是和保留策略匹配得上。通道和格式也值得聊兩句。通道代表一個備份流allocate channel c1 device type disk指定走磁盤。并發(fā)備份時多開幾個通道比如四個通道并行可以明顯壓縮備份耗時但也會提高 I/O 壓力生產上需要結合磁盤性能來定。format /backup/rman/%U里的%U是唯一文件名生成符保證不同備份片不重名。如果希望備份集壓縮可改成backup as compressed backupset database ...但壓縮會占用 CPU需要評估是否值得。還有一個很容易被忽略的動作備份完成后做一次validate。嚴格來說validate是驗證備份文件可讀性和數(shù)據(jù)塊完整性不是恢復數(shù)據(jù)庫。比如RMAN validate backupset 33;它會讀取備份集確認里面的數(shù)據(jù)文件塊能正常讀出來。這種校驗成本比真正恢復低很多建議周備份執(zhí)行后跑一次至少能提前發(fā)現(xiàn)備份集損壞的問題。2.4 保留策略怎么設置保留策略回答的問題是RMAN 到底應該保留哪些備份和歸檔日志才算夠用兩種常見配置是恢復窗口和冗余。RMAN CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;恢復窗口 7 天表示數(shù)據(jù)庫必須能夠恢復到過去 7 天內的任意時間點。RMAN 會根據(jù)這個窗口自動判斷哪些備份集和歸檔日志可以標記為 obsolete在后續(xù)執(zhí)行delete obsolete時清理。另一種是按冗余度RMAN CONFIGURE RETENTION POLICY TO REDUNDANCY 2;表示每個數(shù)據(jù)文件至少保留兩份可用的備份副本。窗口更長或冗余越多占用空間越大。具體怎么設取決于業(yè)務允許丟失的數(shù)據(jù)量和可用磁盤空間。一個小建議保留窗口別設成 30 天除非你有專門的歸檔存儲否則備份和歸檔會占掉大量磁盤清理動作追不上生成速度最后歸檔堆積問題會出現(xiàn)得比想象快。先定業(yè)務要求再反推空間規(guī)劃這是比較健康的做法。3. 刪除歸檔安全清理的完整流程與關鍵坑點3.1 歸檔日志為什么會越堆越多歸檔堆積通常是幾個問題疊加。最典型的是備份腳本里根本沒有backup archivelog這一段只做了數(shù)據(jù)文件備份歸檔日志就一直堆在 FRA 里沒人管。還有一種是 DBA 覺得“刪除歸檔就是清理磁盤”于是定期手動執(zhí)行delete archivelog all但沒有關聯(lián)備份策略結果刪得過于激進真正需要恢復時反而缺文件。業(yè)務側的原因也不可忽視。某些批量導入、全表更新、索引重建操作會產生大量 redo如果日志切換頻率高到每幾分鐘切一次一晚上生成幾百份歸檔很正常。我記得有次接手批量任務只跑了一小時FRA 空間就掉了 30%到了晚間高峰直接把磁盤寫滿所有事務卡在日志切換上數(shù)據(jù)庫從“可用”變成“半掛”狀態(tài)。那種場景下第一步永遠不是討論為什么堆積而是要先把已備份的歸檔安全清理掉騰出空間讓系統(tǒng)恢復運行。3.2 標準操作交叉校驗、確認備份、再刪除在我的操作習慣里手動清理歸檔會按固定順序走不直接上來就delete archivelog all。第一步先做交叉校驗RMAN crosscheck archivelog all;crosscheck的動作是把控制文件里記錄的歸檔日志和磁盤或帶庫上的實測文件做對照。有些文件可能被操作系統(tǒng)直接刪除了但你并不知道如果不做這步RMAN 會認為文件還在后續(xù)刪除時就會報找不到文件的錯誤。交叉校驗后找不到的歸檔會被標記為 expired它不是備份也沒關系接下來可以清理掉這些狀態(tài)記錄RMAN delete expired archivelog all;第二步確認這些歸檔日志是否已經有備份。最好的確認方式是有backup archivelog或backup database plus archivelog日志輸出。也可以在 RMAN 里先查看RMAN list backup of archivelog all;我一般會看輸出的范圍是否覆蓋到今天。如果覆蓋不到我絕不會直接刪更早的歸檔因為一旦后面需要介質恢復缺口就會導致無法繼續(xù)。第三步才執(zhí)行真正的刪除。按天數(shù)保留的寫法最有價值RMAN delete noprompt archivelog until time sysdate-7;這條命令先列出所有 7 天前的歸檔然后自動刪除。我建議執(zhí)行時先不帶noprompt試跑一次讓 RMAN 列出將被刪除的清單人工掃一眼再正式執(zhí)行避免誤刪近期重要歸檔。對于絕大多數(shù)業(yè)務保留 7 天歸檔已經覆蓋恢復窗口如果你的全備每天都做甚至可以只保留到上次全備時間點之前讓空間占用更少。3.3 刪除歸檔的三種命令和各自場景刪除歸檔常見寫法有三種適用場景不同第一種是“備份即刪除”也就是backup archivelog all delete input或backup database plus archivelog delete input。這種方法最推薦日常使用因為它要求歸檔日志先進入備份集然后才刪原始文件不會出現(xiàn)“備份還沒做文件先沒了”的尷尬。第二種是手動按時間刪除如delete archivelog until time sysdate-7。適合你已經確定歸檔文件本身不再需要或者另外有工具備份了那些文件。需要注意這里的保留天數(shù)并不是 RMAN 自動判斷的而是你人為指定的所以要確保時間范圍的判斷合理。第三種是直接清空全部歸檔如delete noprompt archivelog all。這條命令風險最大通常只在歸檔目錄完全被塞滿、業(yè)務緊急恢復運行時才使用。使用這種命令前務必先確認你接受的數(shù)據(jù)丟失風險并且在刪完后立刻觸發(fā)一次新的全備保證后續(xù)恢復點存在。否則一旦此刻發(fā)生數(shù)據(jù)文件損壞能恢復的位置會非常慘淡。3.4 三個我實測過的坑看看你中過哪個坑一把delete obsolete當成歸檔清理命令。很多新手以為執(zhí)行完delete obsolete就會釋放歸檔空間實際上它清理的依據(jù)是保留策略清理對象是那些被標記為過期的備份集和備份片。歸檔日志本身的原始文件并不會因為delete obsolete被刪除除非它們作為備份集內容一起被判定過期。所以如果你發(fā)現(xiàn)歸檔占滿磁盤正確的思維路徑是先backup archivelog ... delete input或delete archivelog而不是糾結為什么delete obsolete沒效果。坑二歸檔文件被手動 rm 后沒有交叉校驗直接刪除。假設你在操作系統(tǒng)層面手動刪了幾個歸檔文件然后執(zhí)行delete archivelog all;RMAN 會報錯提示找不到文件看起來就像命令失敗。這里的問題不是命令本身而是控制文件記錄的元數(shù)據(jù)和磁盤實際情況不一致。解決方式就是先crosscheck archivelog all;再用delete expired archivelog all;讓 RMAN 先對賬再清理無效記錄。整個過程跑通只需要幾秒?yún)s能讓你的清理腳本變得安靜又可靠??尤齻浞莺蛿?shù)據(jù)庫放在同一塊磁盤上。delete input的安全性假設是“備份和原始文件不同盤”。如果備份集也放在數(shù)據(jù)庫主機的那塊數(shù)據(jù)盤上磁盤一壞備份和歸檔同時都沒了所謂備份就只是形式上存在。生產環(huán)境里備份存儲必須和數(shù)據(jù)庫存儲隔離至少是獨立磁盤最好是異地或者云對象存儲具體視團隊資源而定。這個原則比任何具體的刪除命令都重要因為它決定了刪除歸檔后是否還有可恢復的退路。4. 備份的最終目的恢復實操與故障排查4.1 restore 和 recover 先分清楚恢復不是一個動作而是兩個階段。restore是把備份集里的物理文件還原回數(shù)據(jù)庫目錄例如把損壞的數(shù)據(jù)文件從備份中拷貝回來recover則是把歸檔日志和當前 redo log 應用到這些還原后的數(shù)據(jù)文件上使它們推進到一致或指定的時間點。你可以粗淺地理解為restore 是“把上次備份還原”recover 是“把備份之后的賬補上”。這是我反復強調的一點因為在排查恢復問題時顯得尤為重要。如果 restore 做完直接 open數(shù)據(jù)庫經常報不一致錯誤因為你看到的是某個舊時間點的狀態(tài)recover 還沒執(zhí)行。反過來如果歸檔日志缺失recover 會中途停下此時究竟跳過還是轉為不完全恢復需要仔細判斷。4.2 數(shù)據(jù)文件損壞恢復的完整過程假設一個多數(shù)的場景數(shù)據(jù)庫還在運行但某個數(shù)據(jù)文件損壞即使數(shù)據(jù)庫可能提示異常。第一步把損壞文件離線SQL alter database datafile 4 offline;然后用 RMAN 恢復這個文件RMAN restore datafile 4; RMAN recover datafile 4;最后重新上線SQL alter database datafile 4 online;這是在線文件級恢復整個數(shù)據(jù)庫不需要關閉只影響文件 4 所在的表空間?;謴屯瓿珊髍ecover會應用文件離線期間產生的所有必要 redo包括歸檔日志和在線日志最終把該數(shù)據(jù)文件和其他文件對齊到同一個 SCN。如果損壞范圍較大或者控制文件也丟了那就需要整個數(shù)據(jù)庫恢復RMAN startup mount; RMAN restore database; RMAN recover database; RMAN alter database open;此處的recover database會自動應用備份后到當前時刻的歸檔日志數(shù)據(jù)庫能夠恢復到盡量接近故障時刻的狀態(tài)。4.3 不完全恢復與 resetlogs 的配合當業(yè)務誤刪了某張表或者希望恢復到某個誤操作之前的時間點就需要不完全恢復。流程是先定位精確時間或 SCN再執(zhí)行RMAN run { set until time to_date(2024-06-20 09:30:00,yyyy-mm-dd hh24:mi:ss); restore database; recover database; alter database open resetlogs; }set until time指定恢復目標時間點RMAN 會找到該時間點之前最近的數(shù)據(jù)文件備份和一系列歸檔日志把數(shù)據(jù)庫恢復到那個時刻。這里的resetlogs是不完全恢復之后的固定動作它會重置聯(lián)機重做日志的 sequence生成一條全新的日志歷史分支。執(zhí)行完resetlogs后數(shù)據(jù)庫就能以新的日志序列繼續(xù)運行。這里必須強調一個后續(xù)動作不完全恢復后立即做一次全備。因為resetlogs改變了日志序列舊的備份和歸檔日志在恢復鏈路里可能與新的日志分支不再銜接原有備份集對于新序列的數(shù)據(jù)庫來說不能直接用于恢復到更早的時間點。所以“恢復完成”不是終點備份重新生成才是。4.4 恢復失敗時怎么排查恢復過程中最常見的是ORA-00283或ORA-01110它們往往指向缺失或損壞的歸檔日志。排查思路分四步查看告警日志alert log其中記錄了恢復嘗試時遇到的錯誤和具體文件路徑。查詢動態(tài)視圖SQL SELECT * FROM v$recovery_log;這個視圖會列出恢復過程中需要應用的歸檔日志序列范圍以及已應用和待應用的狀態(tài)。配合v$log_history可以定位缺失文件。判斷是否可以做完全恢復。如果缺失的歸檔發(fā)生在恢復路徑中間后續(xù)歸檔就算存在也無法連續(xù)應用完全恢復不可能了。此時要么找備份源把缺的歸檔restore archivelog回來要么退而求其次把set until time定位在缺失歸檔之前最近的一個可用時間點做不完全恢復。如果換了主機或控制文件被重建RMAN 可能認不出備份集。這時用目錄導入命令重新注冊備份目錄RMAN catalog start with /backup/rman;執(zhí)行完它會把目錄下的備份片信息寫回控制文件或目錄庫RMAN 就能找到可用的備份集再繼續(xù) restore。很多“備份明明在卻恢復不了”的詭異情況根本原因就是備份集沒有被 RMAN 的元數(shù)據(jù)識別。5. 監(jiān)控歸檔增長與日常運維建議5.1 用視圖實時觀察歸檔和備份狀態(tài)與其等歸檔把磁盤占滿再搶救不如把監(jiān)控提前做起來。最常用的視圖是v$recovery_area_usageSELECT * FROM v$recovery_area_usage;它給出快速恢復區(qū)里各個文件類別歸檔日志、備份集、閃回日志等的使用率。如果歸檔日志的百分比持續(xù)超過 70%~80%說明歸檔清理沒跟上需要檢查最近一次備份是否成功、delete input是否真的生效。日志切換頻率也可以監(jiān)控SELECT TO_CHAR(first_time, yyyy-mm-dd hh24) hour, COUNT(*) FROM v$log_history WHERE first_time sysdate - 7 GROUP BY TO_CHAR(first_time, yyyy-mm-dd hh24) ORDER BY 1;如果某些的每小時切換數(shù)量異常多說明該時段 redo 生成量很大可能是夜間批量任務或調度作業(yè)產生的。我見過一條低效的 update 語句每小時觸發(fā)幾十次日志切換歸檔文件數(shù)量暴漲直接把 FRA 撐爆。這類問題光靠刪歸檔只是治標還需要配合 SQL 調優(yōu)、調整批量任務或者日志組大小才能降低 redo 產生速率。5.2 把備份、清理、監(jiān)控做成閉環(huán)最后聊聊日常運維的閉環(huán)設計而不是零散的命令。我推薦在定期流程里組合下面幾件事每天按策略執(zhí)行一次數(shù)據(jù)文件備份全備或增量命令中帶上plus archivelog delete input讓歸檔清理自動發(fā)生。配置保留策略為RECOVERY WINDOW OF 7 DAYS或符合業(yè)務需求的窗口執(zhí)行delete obsolete清理過期的備份集。每周至少跑一次crosscheck archivelog all和crosscheck backup再執(zhí)行delete expired把外力刪除文件產生的元數(shù)據(jù)殘留清掉。每個月或每兩個季度做一次真實的恢復演練把 RMAN 備份恢復到測試環(huán)境驗證備份可用的狀態(tài)。構建這個閉環(huán)的動機來自一個教訓很多環(huán)境備份跑得很勤但從沒驗證過恢復路徑最后真出問題時才發(fā)現(xiàn)某個備份片損壞、歸檔空缺、控制文件信息不完整?;謴脱菥毜囊饬x就是在真正出事前把這些缺陷暴露出來把“理論上能恢復”變成“實測能恢復”。我個人在實際操作中的體會是RMAN 備份恢復和刪除歸檔真正考驗人的不是某條命令怎么寫而是你是否能把備份和刪除放在同一條安全的邏輯鏈路上先有備份再刪原始歸檔先有元數(shù)據(jù)一致再動文件先有恢復演練再放心的策略。最后再分享一個小技巧每次手工刪除歸檔之后順手執(zhí)行一下list backup summary;和list archivelog all;確認 RMAN 記錄的狀態(tài)和磁盤上真實情況一致。幾次之后你會對自己這套數(shù)據(jù)庫的歸檔生成速度、空間占用節(jié)奏形成非常直觀的判斷應對突發(fā)狀況時心里也就不慌了。