干我们这行的,最怕半夜手机响。十次里有八次,不是“服务器挂了”,就是“数据库起不来了”。尤其是SQL Server,平时安安静静跑得好好的,一旦出事,“恢复数据库”这几个字就成了紧箍咒。今天不聊那些官方文档里的术语,就说说我这些年亲手折腾过的恢复路子、踩过的坑,还有那些能救命的小技巧。

先说最常见的一种情况:数据库没坏,就是被误删了文件,或者系统崩溃后文件还在,但实例起不来了。这时候别慌,先看看有没有完整的备份文件。有备份,事情就简单了一大半。在SSMS里右键数据库,选“还原数据库”,源设备选你的.bak文件,目标数据库名填好,点上“覆盖现有数据库”,基本就完事了。但这里有个坑,很多人忽略——还原选项里的“恢复状态”。如果选的是“RESTORE WITH RECOVERY”,数据库就能直接用了;但如果你还想继续还原后续的日志备份,必须选“RESTORE WITH NORECOVERY”,让数据库处于“正在还原”状态。这个细节,新手十有八九栽在这上面。
可要是没有备份呢?那就得动真格的了。SQL Server的MDF和LDF文件,前者是数据主文件,后者是日志文件。如果两个文件都还在,只是实例崩了,你可以尝试附加数据库。右键“附加”,选上MDF文件,系统会自动找对应的LDF。但有时候LDF丢了或者坏了,附加会报错。这时候有个偏方——先创建一个同名的新数据库,然后停止SQL Server服务,用你那个旧的MDF文件覆盖新生成的MDF文件,再启动服务。运气好,系统会认为这个库是自己创建的,自动重建日志。这招我救过一个客户的考勤系统,但得提醒你,只适用于日志文件损坏但数据文件完整的情况,而且有风险,操作前最好把原文件备份一份。
再说说日志文件完好、但数据文件损坏的情况。这相对好办一点,但需要点耐心。先把数据库设为紧急模式,执行,然后尝试重建日志。如果还不行,就用挨个检查页面错误。注意,这一步极耗CPU和IO,别在业务高峰期跑。跑完如果有修复项,再用。看到“ALLOWDATALOSS”这几个字没?意思是允许丢数据。所以跑之前,一定一定再确认一遍备份情况,否则修复完发现少了关键表,哭都来不及。
还有一种更隐蔽的故障——数据库显示“可疑(SUSPECT)”。这词儿听着就吓人,但大部分时候是日志文件和控制信息不一致。最简单的处理办法,是先把数据库脱机,然后重新联机。在SSMS里点“脱机”,再点“联机”,有时候就能自动恢复。如果这招没用,就得手动改系统表,把状态从可疑改成紧急。具体SQL是,然后,修复。修完再改回多用户模式。这套组合拳我打过好几次,成功率大概七成,剩下的三成,老老实实找备份吧。
聊到备份策略,我得说句得罪人的话——很多人以为每天做一次完整备份就万事大吉,这是天真。SQL Server的恢复粒度,取决于你的日志备份频率。如果你只做每日全备,那最多只能恢复到昨天那个时间点,今天一天的数据全丢。正确做法是:每周一次全备,每天一次差异备份,每15分钟或者半小时一次日志备份。这样出事儿,最多丢半小时的数据。我之前有个客户,财务系统,就是靠这个策略,在磁盘阵列坏了一块的情况下,只丢了3分钟的数据,老板差点没给我跪下。
但备份文件本身也可能是个坑。我遇到过备份文件完好、但元数据损坏的情况。还原时报错“备份集有效,但无法应用”。这时候别急,试试先验证一下备份的完整性。如果验证通过但还原失败,大概率是旧库还占着名字,或者有活动连接。先杀掉所有连接,把库删了再还原。还有个小技巧,用查看备份文件里到底包含了哪些内容,有时候一个.bak里塞了好几个数据库的备份,你得用和选项重新指定逻辑文件名和物理路径。这活儿我干过太多次了,每次都得记下逻辑名,不然还原出来路径全是乱的。
说一个高级点的场景——时间点恢复。比如你早上10点误删了一张表,想恢复到9点59分的状态。如果你有完整的日志备份链,完全可以做到。先还原全备(NORECOVERY),再还原一次差异备份(NORECOVERY),然后逐个还原日志备份,直到你想恢复的那个时间点的前一个日志。一个日志备份用来指定截止时间。SQL Server会自动把日志截断到那个点。我有个同事,误删了一个月的销售记录,就是用这个方法救回来的,当时他手都在抖。但记住,前提是你的日志链没断过,中间哪怕有一次用了SIMPLE恢复模式,这招就废了。
说实话,SQL Server恢复数据库这事儿,说到底是三分技术七分准备。技术再牛,没有备份文件,也是巧妇难为无米之炊。我见过太多人,平时不重视备份策略,出了事就到处求爷爷告奶奶找数据恢复公司,一张嘴就是几万块。其实只要你把全备、差异、日志备份这三级策略做好,把恢复步骤在测试环境演练过几遍,真出了事,按部就班操作,绝大多数情况都能自己搞定。再啰嗦一句——恢复完成后,第一时间做一次完整备份,把你刚恢复的库变成新的基准点,别让旧的备份链卡在中间。这行当,细心比能力值钱。


