SQL Server MDF 損壞?數據庫修復實戰指南

SQL Server MDF 損壞?數據庫修復實戰指南
上個月底,觀塘有間物流公司,朝早返工發現成個 ERP 開唔到,彈出「Database 'LOGISTICS_DB' cannot be opened due to inaccessible files or insufficient memory」。IT 主管即刻打俾我哋,把聲好急:「入面有成 5 年嘅出貨記錄,聽日要報稅,冇咗呢個 database 真係大鑊。」我哋 remote 入去睇,個 MDF 檔仲喺度,但係 SQL Server 話佢 suspect——呢個係數據庫損壞嘅典型症狀。今日講下 SQL Server 損壞嘅原因、點樣修,同埋點樣避免下次再發生。
SQL Server 損壞嘅常見原因
- 突然斷電/server 死機:最常見。SQL Server 寫入嗰陣有嚴格嘅次序(write-ahead logging),斷電嗰陣如果寫到一半,個 MDF 同 LDF 就會唔一致。下次開機嗰陣,SQL Server 做 crash recovery,如果 LDF 都損埋,就會標記 suspect。
- 硬碟壞道:MDF 檔好大(幾個 GB 到幾百 GB),橫跨好多 sector。如果壞道啱啱喺個 data page 上面,嗰頁就讀唔到。SQL Server 會報 823、824 或者 825 錯誤(I/O 錯誤)。
- RAID 出問題:database 放喺 RAID 上面,如果 RAID degraded 或者 rebuild 緊嗰陣出事,寫入嘅資料可能唔完整。我哋見過 RAID 5 rebuild 失敗之後,個 MDF 有幾頁係舊資料同新資料溝埋。
- 人為誤刪:有人 delete 咗個 LDF(log 檔),以為唔重要。冇咗 LDF,SQL Server 開唔到個 database,因為佢要靠 log 做 recovery。呢種其實易搞,attach 返個 MDF rebuild 個 log 就得。
- 病毒/勒索軟件:勒索病毒唔止加密 Office 檔,MDF、BAK 呢啲都會加密埋。有客成個 SQL Server folder 俾人加密,連 backup 檔都唔放過。
第一步:判斷損壞程度
唔好一嚟就撳 repair。正確流程係先診斷:
- 睇 SQL Server error log:入 SQL Server Management Studio(SSMS),睇下個 database 係咩狀態——SUSPECT、RECOVERY_PENDING、定係 OFFLINE。每種狀態唔同處理方法。
• SUSPECT:SQL Server 開唔到個 database,多數係 MDF 或者 LDF 損毀
• RECOVERY_PENDING:SQL Server 知道有問題,但係未放棄,有機會自動修復
• OFFLINE:人手或者系統將佢 offline 咗,可能唔關損壞事 - 做 DBCC CHECKDB:如果個 database 仲開得到(或者開得到 single user mode),跑:
DBCC CHECKDB ('LOGISTICS_DB') WITH NO_INFOMSGS;呢個會逐頁檢查,話你知邊啲 page 損壞、邊個 table 受影響、損壞有幾嚴重。 - 檢查硬碟健康:如果係 I/O 錯誤(823/824),先檢查硬碟 S.M.A.R.T.。如果隻碟就嚟死,唔好再喺上面跑 CHECKDB——每一次讀取都係折磨。先將個 MDF/LDF 抄去第二隻健康嘅碟,喺嗰度做診斷。
• 唔好 delete 個 LDF 諗住「等佢自己重建」——冇咗 log,有啲損壞修唔返
• 唔好直接喺原檔上面跑 DBCC CHECKDB REPAIR——REPAIR_ALLOW_DATA_LOSS 真係會唔見資料,要喺備份上面試先
• 唔好 restore 個舊 backup 落同一個 database 名——會覆蓋,而家個損壞咗嘅版本可能仲有啲救得返嘅嘢
觀塘個案:點樣救返個 ERP
講返開頭嗰單。個 MDF 280GB,LDF 15GB。CHECKDB 結果:有 47 個 page 損壞,集中喺兩個 table——一個係出貨記錄主表,一個係索引。好彩,最核心嘅會計憑證表冇事。
我哋嘅處理步驟:
- 完整備份現狀:將成個 MDF 同 LDF 抄多一份去我哋部機。之後所有操作都喺副本上面做,原檔封存。呢步唔可以 skip——萬一修壞咗,仲有得返轉頭。
- 試 EMERGENCY mode:
ALTER DATABASE LOGISTICS_DB SET EMERGENCY; DBCC CHECKDB ('LOGISTICS_DB') WITH NO_INFOMSGS;EMERGENCY mode 會 bypass 正常嘅 recovery,等我哋可以直接讀個 MDF,睇下損壞有幾深。 - 逐表導出:唔好成個 database repair——因為 REPAIR_ALLOW_DATA_LOSS 會直接 delete 損壞嘅 page,啲資料就真係唔見。我哋嘅做法係逐個 table 用 bcp 或者 SELECT INTO 導出,損壞嘅 table 就逐行試,讀到幾多得幾多。
bcp "SELECT * FROM [LOGISTICS_DB].[dbo].[ShippingRecords]" queryout "D:RecoverShippingRecords.bcp" -S localhost -T -n
- 重建新 database:開個全新嘅空白 database,將救返嘅 table 逐個 import 入去。損壞嗰兩個 table,救返約 93% 行數——唔見咗嘅主要係最近三日嘅出貨記錄(啱啱寫入壞道位置)。
- 對數:將救返嘅數據同客手上嘅紙本單據、Excel 對,補返唔見咗嗰三日嘅資料。呢部份要客自己配合,我哋提供個缺失清單。
成單用咗兩日,收 $12,000。IT 主管話:「好彩核心會計數冇事,唔係報稅都報唔到。」之後我哋幫佢哋 set 咗每日自動 backup(full + differential + log backup),同埋將個 MDF 搬去 RAID 6 陣列。
DBCC CHECKDB REPAIR 到底做緊咩?
好多 IT 人聽過 REPAIR_ALLOW_DATA_LOSS,但係唔知佢實際做咩。簡單講,佢有三個級別:
- REPAIR_FAST:淨係修啲唔使唔見資料嘅小問題,例如 index 唔一致。已經 deprecated,而家唔用。
- REPAIR_REBUILD:重建損壞嘅 index。唔會唔見資料,但係只係醫到 index 損壞,data page 損壞醫唔到。
- REPAIR_ALLOW_DATA_LOSS:終極手段。佢會直接將損壞嘅 data page 由個 database 度剷走,等個 database 可以重新上線。個名已經講明——會唔見資料。有幾多頁損壞,就唔見幾多頁嘅資料。
我嘅建議:REPAIR_ALLOW_DATA_LOSS 係最後手段,而且一定要喺副本上面跑,唔係原檔。跑之前,一定要同客講清楚會唔見幾多,客 OK 先好撳。好多時,逐表導出嘅方法救得更多,因為 REPAIR 係成頁剷走,但係逐行導出可能嗰頁入面十行有八行仲讀到。
冇咗 LDF 點算?
呢個係常見問題。有人唔小心 delete 咗個 .ldf,或者個 ldf 損毀到開唔到。可以咁樣 rebuild:
-- 先將 database 設為 EMERGENCY ALTER DATABASE [YourDB] SET EMERGENCY; -- 然後 single user mode ALTER DATABASE [YourDB] SET SINGLE_USER; -- 用 REBUILD_LOG 重建個 log DBCC CHECKDB ([YourDB], REPAIR_ALLOW_DATA_LOSS); -- 記得 set 返 multi user ALTER DATABASE [YourDB] SET MULTI_USER;
但係要注意:rebuild 個 log 之後,之前未 checkpoint 嘅 transaction 會唔見。如果個 database 係喺大量寫入嗰陣死,唔見嘅可能唔少。所以平時一定要做 log backup,唔好淨係做 full backup。
點樣預防下次再發生?
- 備份策略要完整:唔係淨係 full backup。要做:每日 full backup(夜晚)+ 每 4 小時 differential + 每 15 分鐘 log backup。咁樣就算 MDF 死,最多唔見 15 分鐘資料。
- Backup 要驗證:有 backup 唔等於有得還原。每個月抽一個 backup 做 test restore,確保開得到。我哋見過有客 backup 咗三年,從來冇試過還原,出事嗰陣先發現啲 backup 檔全部損壞。
- 將 MDF 放喺可靠嘅儲存:RAID 6 或者 RAID 10,唔好放喺單隻碟或者 RAID 0。Database 嘅 I/O 好頻密,碟死嘅機會比一般 file server 高。
- 開返 CHECKSUM:SQL Server 有個 page checksum 功能,寫入嗰陣會計個校驗碼,讀出嚟嗰陣對。開咗之後,壞道會早啲發現,唔會靜靜哋爛落去。
ALTER DATABASE [YourDB] SET PAGE_VERIFY CHECKSUM;
- 監察硬碟健康:SQL Server 唔會話你知隻碟就嚟死。要另外用 S.M.A.R.T. 監察,或者買個簡單嘅 monitoring。我哋幫客 set 親 database server,一定會加埋硬碟監察。
收費參考
- 純邏輯損壞(DBCC 修到):$4,000-$8,000,1-2 日
- 要逐表導出重建:$8,000-$15,000,2-4 日
- MDF 物理損壞(硬碟壞道):$12,000-$25,000,要先做硬碟鏡像,5-7 日
- 勒索病毒加密:視乎情況,如果連 backup 都加密埋,可能救唔返。先免費評估。
FAQ
1. 問:個 database 顯示 SUSPECT,我重啟 SQL Server 會唔會自己好返?
答:唔會。SUSPECT 即係 SQL Server 已經試過 recovery 但係失敗。重啟只會再試多次,結果一樣。而且每次重啟都有機會令情況更差(例如觸發自動修復)。正確做法係停喺度,先備份個 MDF/LDF,然後診斷。
2. 問:我有舊 backup,可唔可以直接 restore?
答:可以,但係有兩點要注意:第一,restore 會用舊資料覆蓋,而家個損壞版本入面可能仲有啲新資料救得返,應該先將而家個版本救咗先;第二,restore 去一個新嘅 database 名(例如 LOGISTICS_DB_RESTORE),唔好直接覆蓋原來嗰個,等確認啲資料啱先至 swap。
3. 問:Express 版同 Standard 版喺修復上有冇分別?
答:修復方法一樣,但係 Express 版有 10GB database 上限。如果個 MDF 超過 10GB,Express 版根本 attach 唔到,要用 Standard 或者 Developer 版嚟做恢復。我哋有齊唔同版本,唔使擔心。
4. 問:個 MDF 有 500GB,恢復要幾耐?
答:視乎損壞程度同硬碟速度。純邏輯問題,CHECKDB 可能要跑幾個鐘(500GB 逐頁 check 好花時間)。如果要逐表導出,視乎 table 數量,可能要 2-4 日。我哋會先做初步檢查,俾個實在嘅時間預算。
總結
SQL Server 損壞唔係世界末日,但係處理次序好重要:備份現狀 → 診斷 → 喺副本上面修 → 逐表驗證。千祈唔好喺原檔上面亂試 REPAIR,唔好 delete 個 LDF,唔好直接 restore 覆蓋。如果你而家個 database 已經 suspect,停手,WhatsApp +852 6558 6806,我哋有處理過百 GB 大 database 嘅經驗,免費初步評估。
覺得這篇文章有幫助?
歡迎分享給您的朋友或同事。