據(jù)庫不慌:SQL Server事務(wù)日志與ApexSQL Log恢復(fù)實踐)
簡介面對誤刪數(shù)據(jù)庫的緊急場景這份ApexSQL Log 誤刪數(shù)據(jù)庫還原破解版工具包能幫助DBA、運(yùn)維與開發(fā)人員從事務(wù)日志層面快速定位并恢復(fù)數(shù)據(jù)支持多種數(shù)據(jù)庫版本實測在SQL Server 2008下運(yùn)行穩(wěn)定適合需要處理誤刪、日志損壞或數(shù)據(jù)異常的中高級數(shù)據(jù)庫使用者。資源包為zip壓縮格式整體約26.11MB部署后在Windows環(huán)境中即可調(diào)用通過解析數(shù)據(jù)庫日志文件完成數(shù)據(jù)還原。目前已有599人學(xué)習(xí)/下載是應(yīng)急恢復(fù)場景中值得收藏的實用工具。借助該工具用戶可深入分析事務(wù)日志內(nèi)容、篩選誤刪操作、還原指定時間點數(shù)據(jù)也能用于日常日志排查與審計。無論是意外刪除重要業(yè)務(wù)表還是需要審計歷史操作記錄該工具都能提供日志級還原思路與執(zhí)行入口對使用舊版數(shù)據(jù)庫的團(tuán)隊尤其實用。 誤刪數(shù)據(jù)庫之后的第一反應(yīng)絕大多數(shù)人都是找備份、跑恢復(fù)可一旦備份時間點不夠新、庫太大恢復(fù)耗時長、或者壓根沒開日志備份那種眼睜睜看著數(shù)據(jù)找不回來的感覺我相信不少DBA和運(yùn)維都體會過。我去年處理過一起業(yè)務(wù)人員誤DROP表的故障最后就是靠ApexSQL Log從在線事務(wù)日志里把刪除的數(shù)據(jù)一條條撈回來的。這篇文章就把完整的思路、原理、操作步驟以及為什么我不碰所謂ApexSQL Log破解版這件事一次講清楚。如果你做SQL Server數(shù)據(jù)庫維護(hù)或者平時兼著管庫的后端開發(fā)、運(yùn)維這篇內(nèi)容可以直接抄作業(yè)。注意兩個前提ApexSQL Log是SQL Server專用工具別拿去套MySQL、Oracle、達(dá)夢這些數(shù)據(jù)庫另外你在事故發(fā)生時如果用的是簡單恢復(fù)模式那就別抱太多幻想下面的原理部分會解釋為什么。1. 誤刪事故的典型現(xiàn)場備份還原為什么常常兜不住1.1 最常見的幾種誤刪姿勢先說場景。我接觸過的誤刪故障觸發(fā)原因翻來覆去就那么幾類清理數(shù)據(jù)時寫DELETE語句沒加WHERE條件或者WHERE條件寫錯導(dǎo)致整表被清。業(yè)務(wù)腳本里直接寫了DROP TABLE / TRUNCATE TABLE本想只清臨時表結(jié)果因為庫名、表名寫錯刪了正式表。批量任務(wù)把測試環(huán)境的腳本帶到生產(chǎn)環(huán)境執(zhí)行連庫名都沒改。還有一類最隱蔽先執(zhí)行了什么操作然后過了一段時間才發(fā)現(xiàn)數(shù)據(jù)影響日志早就被后續(xù)事務(wù)覆蓋了一部分。這些場景的共同點是操作發(fā)生前沒有人專門做過一次針對該表的備份。常規(guī)備份策略是凌晨全量備份、白天定期差異或日志備份所以最尷尬的情況就是——早上10點誤刪了9點的數(shù)據(jù)全量備份在凌晨中間差了好幾個小時的數(shù)據(jù)只能靠日志去找。1.2 備份還原的無力點不是所有情況都能用備份恢復(fù)解決。你可能會遇到幾個現(xiàn)實問題第一備份粒度不夠。全量備份加差異備份最多恢復(fù)到最近一次備份時間點備份之后到誤刪前的數(shù)據(jù)變化全部丟失。第二恢復(fù)耗時不可控。幾個TB的大型庫從備份恢復(fù)到可用狀態(tài)可能以小時計業(yè)務(wù)方根本等不起。第三覆蓋式恢復(fù)會沖掉現(xiàn)有數(shù)據(jù)。如果你把整個庫恢復(fù)到誤刪前的時間點那誤刪之后新增的數(shù)據(jù)也會被一起抹掉這在業(yè)務(wù)上往往不可接受。所以在這種情況下日志級還原的價值就出來了不動整體備份只從事務(wù)日志里提取與誤刪相關(guān)的記錄生成對應(yīng)的反向操作腳本把丟掉的數(shù)據(jù)補(bǔ)回去。1.3 ApexSQL Log 在這里扮演的角色ApexSQL Log 本質(zhì)上是一個日志解析和恢復(fù)工具。它不依賴你手頭有沒有完整備份而是直接讀取SQL Server的事務(wù)日志文件在線日志或日志備份文件把里面的INSERT、UPDATE、DELETE、TRUNCATE、DROP等操作識別出來然后針對某個特定的時間點、某個特定的表生成一條或多條反向操作腳本。聽起來像黑科技實際上原理并不復(fù)雜但前提條件比較苛刻。下一節(jié)我詳細(xì)拆開講。2. ApexSQL Log能找回數(shù)據(jù)的原理事務(wù)日志不是流水賬是后悔藥2.1 事務(wù)日志到底記了些什么SQL Server的每個數(shù)據(jù)庫都有事務(wù)日志文件通常是.ldf也可能配置了多個日志文件。數(shù)據(jù)庫上執(zhí)行的每一個寫操作都會先寫入事務(wù)日志再寫入數(shù)據(jù)文件。這個機(jī)制叫預(yù)寫日志W(wǎng)rite-Ahead Logging。普通同事不太會注意日志文件里的內(nèi)容但對做恢復(fù)的人來說那里面記錄的信息非常關(guān)鍵。一條DELETE操作寫入日志時記錄的不僅僅是刪除了多少行還會把被刪除行的**原始數(shù)據(jù)鏡像之前鏡像before-image**寫進(jìn)日志一條UPDATE會同時記錄更新前的舊值和更新后的新值INSERT則記錄插入的新值。之所以能做到精確還原靠的就是這些鏡像信息。你可以把事務(wù)日志理解為存儲引擎的錄像帶數(shù)據(jù)文件是播放出來的畫面日志記錄的是每一幀畫面變化的過程。只要錄像帶還在就可以倒帶重播找到某一幀的原始狀態(tài)。2.2 工具如何把日志變成UNDO腳本ApexSQL Log做的事就是把這個倒帶過程自動化。它會掃描在線日志或日志備份文件解析其中的日志記錄鏈還原出每一個事務(wù)的操作過程然后給你呈現(xiàn)出一個操作列表。你在界面上看到的不再是二進(jìn)制的日志LSN日志序列號而是一張張可讀的記錄表包含事務(wù)時間、登錄賬號、操作類型、涉及的庫表、影響行數(shù)等。選中一條誤刪操作后工具會根據(jù)這條日志記錄里保存的before-image生成一條反向腳本。比如誤刪的是一條DELETE它就會把刪除前的每條記錄重新生成INSERT語句誤刪的是一條UPDATE它就會把舊值寫回去生成更新語句誤刪的是INSERT就生成對應(yīng)的DELETE語句。2.3 最核心的前提恢復(fù)模式必須是FULL這里必須敲黑板。SQL Server的恢復(fù)模式有三種FULL完整、SIMPLE簡單、BULK_LOGGED大容量日志。ApexSQL Log要恢復(fù)出精確的數(shù)據(jù)前提是你的數(shù)據(jù)庫處于FULL恢復(fù)模式并且發(fā)生過事務(wù)之后日志沒有被截斷或覆蓋。為什么因為SIMPLE恢復(fù)模式下數(shù)據(jù)庫會在每次檢查點之后主動截斷日志——那些記錄著before-image的歷史日志會被清理掉日志文件只保留做崩潰恢復(fù)所需的最小信息。所以如果你用的是SIMPLE恢復(fù)模式誤刪之后ApexSQL Log可能什么都讀不到界面會提示日志中找不到相應(yīng)操作記錄或者日志已被截斷。這也是為什么我接手的很多新項目里第一件事必須確認(rèn)核心庫的恢復(fù)模式。如果你所在環(huán)境還是默認(rèn)的SIMPLE模式現(xiàn)在就應(yīng)該去改。但要注意改恢復(fù)模式不會讓已經(jīng)被截斷的歷史日志長回來所以這個動作要提前做不是等出了事再切。2.4 另一個隱藏條件日志空間不能被覆蓋FULL恢復(fù)模式下日志雖然不會被主動截斷但如果不做日志備份日志文件會持續(xù)增長直到磁盤滿了。很多人一看到日志文件漲到幾十GB就手動收縮日志DBCC SHRINKFILE或者在備份事務(wù)日志后把.ldf縮到很小——這等于把歷史日志清空了。誤刪之后再去看ApexSQL Log能讀到的范圍已經(jīng)斷在某個時間點之前了。所以如果你的還原目標(biāo)時間點在日志被截斷/收縮之前那基本沒戲只有在目標(biāo)事務(wù)發(fā)生后、日志被截斷前這段時間窗口里的操作才找得回來。這也是很多DBA的痛點數(shù)據(jù)刪了但日志空間被反復(fù)收縮過找不回來只能認(rèn)栽。3. 從事故到還原的完整操作路徑以SQL Server為例3.1 事故第一反應(yīng)先止血再分析遇到誤刪第一件事不是打開工具到處點而是停止所有對該庫的寫入操作。你每繼續(xù)寫一筆業(yè)務(wù)數(shù)據(jù)事務(wù)日志就可能繼續(xù)增長甚至覆蓋掉刪除操作前后的關(guān)鍵日志。穩(wěn)妥的做法是把數(shù)據(jù)庫先切換到單用戶模式斷開業(yè)務(wù)連接或者至少在數(shù)據(jù)庫層面禁掉寫權(quán)限。別怕影響業(yè)務(wù)數(shù)據(jù)都沒了繼續(xù)跑業(yè)務(wù)的損失更大。同時立刻檢查兩塊東西數(shù)據(jù)庫是不是FULL恢復(fù)模式目標(biāo)誤刪時間點前后的日志備份文件在不在。如果日志備份文件存在ApexSQL Log可以從備份文件里讀取并不一定要把庫在線。3.2 ApexSQL Log的操作步驟分解下面是我實際跑過一次完整還原的流程照著點就行。第一步打開ApexSQL Log選擇SQL Server實例并登錄指定你要操作的數(shù)據(jù)庫。如果數(shù)據(jù)庫已經(jīng)離線你可以選擇直接附加日志文件如果是在線狀態(tài)通常直接選聯(lián)機(jī)日志讀取即可。第二步選擇日志來源。界面里會讓你選是讀取當(dāng)前在線事務(wù)日志Online Log還是讀取之前備份的日志文件Transaction Log Backups。如果你手頭有事故前的日志備份建議先把在線日志和日志備份文件都加載進(jìn)來時間覆蓋范圍越大越好。第三步設(shè)置過濾條件。按時間范圍鎖定事故前后的時間窗口按操作類型勾選DELETE、UPDATE、INSERT、TRUNCATE等還可以指定具體的表名。注意時間顯示可能是UTC也可能是服務(wù)器本地時間要和業(yè)務(wù)系統(tǒng)確認(rèn)到底以哪個為準(zhǔn)否則找半天可能找錯記錄。第四步查看操作列表。過濾完成后工具會列出一堆事務(wù)記錄每條有事務(wù)開始時間、登錄名、執(zhí)行的操作類型、對象名、影響行數(shù)。別急著全選先在列表里找到觸發(fā)誤刪的那一筆事務(wù)雙擊進(jìn)去看看里面具體影響了哪些表、哪些行。第五步右鍵選中誤刪記錄選擇生成還原腳本Undo Script。工具會彈出一個向?qū)ё屇氵x定生成腳本的目標(biāo)位置通常是把腳本保存為.sql文件更安全。默認(rèn)生成方向是把DELETE變成INSERT如果你誤刪的是UPDATE它會自動生成反向UPDATE語句。第六步檢查腳本。這一步最不能省。生成的腳本會包含標(biāo)識列IDENTITY的處理、外鍵順序、默認(rèn)值約束等內(nèi)容你要確認(rèn)這些約束不會被破壞。特別是表之間有關(guān)聯(lián)關(guān)系時還原順序一旦錯了外鍵會直接報錯。第七步執(zhí)行腳本。強(qiáng)烈建議先在一個事務(wù)里執(zhí)行腳本統(tǒng)計影響行數(shù)確認(rèn)無誤后再提交。如果影響行數(shù)和事故前的記錄數(shù)對不上立刻回滾重新排查過濾條件。3.3 還原過程中我踩過的兩個小坑第一個坑是標(biāo)識列沖突。表里有自增IDENTITY列時直接插入指定ID值可能會因為IDENTITY_INSERT未打開而失敗。ApexSQL Log生成的腳本里一般會自動加SET IDENTITY_INSERT ON但如果你的表和視圖比較復(fù)雜它可能沒法全部覆蓋執(zhí)行前要檢查。第二個坑是外鍵順序。如果被刪的表是父表子表里還有引用數(shù)據(jù)生成腳本時最好把子表數(shù)據(jù)先還原再還原主表。ApexSQL Log會根據(jù)數(shù)據(jù)庫約束自動排序一部分但遇到跨庫引用或者觸發(fā)器里操作的其他表它管不了只能靠人工判斷。實操完記得把數(shù)據(jù)庫從單用戶模式恢復(fù)回來重新開啟業(yè)務(wù)連接。整個還原期間業(yè)務(wù)中斷十幾分鐘到幾十分鐘是正常的提前和團(tuán)隊打招呼別默默操作。4. 為什么我在講這個標(biāo)題時先勸你把破解版從腦子里刪掉4.1 網(wǎng)上流傳的破解版我沒法替你拍胸脯這一類恢復(fù)工具本身比較冷門正版價格不便宜所以網(wǎng)上搜ApexSQL Log下載或ApexSQL Log破解版能找到一堆所謂綠色版、注冊機(jī)、補(bǔ)丁文件。很多數(shù)據(jù)庫運(yùn)維人員碰到緊急事故第一反應(yīng)就是趕緊找個能用的版本顧不上審查來源。但我必須把話說透在數(shù)據(jù)庫維護(hù)這條路上最不該用破解版的就是這類直接讀取管理員級數(shù)據(jù)恢復(fù)工具。原因不復(fù)雜這工具本身需要訪問你的SQL Server實例、讀取日志、生成腳本權(quán)限極高。如果這個軟件被惡意植入后門等于把整個庫的管理權(quán)限交給對方。平時你裝個普通開發(fā)工具中招最多電腦被鎖數(shù)據(jù)還在恢復(fù)工具中招數(shù)據(jù)庫內(nèi)容和備份文件全暴露在風(fēng)險之下。4.2 真正發(fā)生過的惡意場景有些所謂的激活工具壓縮包里除了主程序還會帶一個額外exe運(yùn)行后修改啟動項、開機(jī)自啟、遠(yuǎn)程連接固定C2地址。這類樣本多數(shù)會被殺毒軟件識別但很多運(yùn)維習(xí)慣把這類軟件加入白名單生怕殺軟誤刪了破解補(bǔ)丁結(jié)果給了病毒存活空間。更極端的情況某些破解版會篡改工具生成的SQL腳本在還原腳本末尾追加一段惡意存儲過程或提權(quán)SQL指令。你本來要還原數(shù)據(jù)順手執(zhí)行了腳本等于幫攻擊者把后門裝進(jìn)了數(shù)據(jù)庫。這類攻擊手法在近年來的安全通報里不是沒有涉及數(shù)據(jù)庫的工具鏈正是重災(zāi)區(qū)。4.3 合規(guī)審計風(fēng)險也不輕松企業(yè)內(nèi)部對數(shù)據(jù)庫運(yùn)維工具的使用范圍是有管理制度約束的。軟件未授權(quán)安裝在辦公網(wǎng)或生產(chǎn)網(wǎng)里一旦被安全審計或軟件資產(chǎn)管理掃描發(fā)現(xiàn)責(zé)任人要解釋清楚來龍去脈。很多項目的安全驗收環(huán)節(jié)會核查第三方組件和軟件許可帶著破解工具去參加驗收等于給自己埋雷。另外數(shù)據(jù)庫出了問題需要廠商或外部專家支持時對方看到環(huán)境里用了未經(jīng)授權(quán)工具可能會拒絕承擔(dān)相關(guān)責(zé)任甚至要求先整改再繼續(xù)排查。關(guān)鍵時間點上這種風(fēng)險會無限放大。4.4 不用破解版也有路可走我不是讓你放棄這個工具。ApexSQL官方提供試用版的合法渠道遇到緊急事故臨時申請試用版完全來得及。除此之外還有幾條合法的替代路徑使用官方試用版完成緊急恢復(fù)再評估是否需要購買正式授權(quán)。使用SQL Server自身提供的未公開日志分析函數(shù)比如fn_dblog手工查找日志里的刪除記錄但這更適合技術(shù)研究效率遠(yuǎn)不如專用工具。如果只是數(shù)據(jù)對比和腳本還原可以結(jié)合Redgate等商業(yè)工具做數(shù)據(jù)比較再配合日志審計功能彌補(bǔ)。我在這個標(biāo)題下特意先講破解版風(fēng)險是因為我發(fā)現(xiàn)很多人在搜誤刪數(shù)據(jù)庫還原時并不是不知道正規(guī)流程而是急起來想走捷徑。恢復(fù)數(shù)據(jù)本身就是救火救火時往自己油管里加劣質(zhì)燃料后患更大。5. 比還原更重要的是讓下一次誤刪不再需要ApexSQL Log5.1 恢復(fù)模式與日志備份現(xiàn)在就去確認(rèn)看完前面的原理你應(yīng)該明白一件事ApexSQL Log能幫你本質(zhì)上是因為日志文件在。所以最基礎(chǔ)的兩條配置必須落地核心業(yè)務(wù)數(shù)據(jù)庫務(wù)必使用FULL恢復(fù)模式。如果SIMPLE模式不接受改至少要評估業(yè)務(wù)對數(shù)據(jù)恢復(fù)的要求簽字確認(rèn)風(fēng)險。配置事務(wù)日志備份作業(yè)。頻率根據(jù)業(yè)務(wù)量來繁忙庫可以每15分鐘一次日志備份普通庫至少每小時一次。這樣一旦誤刪可讀取的日志文件是連續(xù)的、有保障的。別等到日志文件漲到幾十GB再去手動收縮收縮日志等于把后悔藥倒掉。真要控制日志大小先做日志備份備份后日志空間可復(fù)用但仍不建議頻繁收縮文件。5.2 誤刪發(fā)生后的不要做清單我整理過一份注意事項每次排障都按這個來不要在誤刪后繼續(xù)執(zhí)行大量寫操作、重建索引、批量導(dǎo)入導(dǎo)出這些都會往日志里追加新事務(wù)增加干擾。不要立刻重啟SQL Server服務(wù)除非確認(rèn)日志文件有問題。服務(wù)重啟本身會觸發(fā)崩潰恢復(fù)和檢查點部分日志上下文信息可能被標(biāo)記為不再需要。不要同時開多個工具去讀同一個日志文件避免某些工具鎖定日志導(dǎo)致程序讀取異常。不要跳過測試環(huán)境驗證直接把生成腳本往生產(chǎn)執(zhí)行。最后這兩點最容易犯。很多人拿到腳本就執(zhí)行結(jié)果因為約束順序問題失敗反而把現(xiàn)場搞得更亂。5.3 個人操作習(xí)慣提前演練我在測試環(huán)境里專門備了一臺小庫每次拿到新版本工具都會做一次完整的刪除-還原演練先建表插數(shù)據(jù)然后刪除記錄再用工具從日志里恢復(fù)。演練完你會對這類工具的邊界心中有數(shù)比如TRUNCATE恢復(fù)是否支持、DROP表之后能否基于日志重建、時間窗口覆蓋多少而不是等生產(chǎn)故障時才第一次摸功能。我的看法是ApexSQL Log這類工具應(yīng)該放在工具架子上當(dāng)應(yīng)急設(shè)備備著但日常的工作重心永遠(yuǎn)是做好日志備份和權(quán)限管控。事故發(fā)生后能用它挽救數(shù)據(jù)是幸運(yùn)平時做好準(zhǔn)備讓自己盡可能不依賴這種幸運(yùn)才是真正穩(wěn)妥的做法。本文還有配套的精品資源點擊獲取