干这行十几年,SQLServer数据库卡在“正在恢复”这种事儿,我碰见的次数比客户请吃饭的次数还多。每次看到那个灰色的状态标签,心里就咯噔一下,尤其是生产环境,业务全停,老板站在背后盯着你刷新页面,那滋味儿真不好受。这问题说白了,就是数据库在启动或者做日志回滚的时候,进程卡住了,系统一直没给个准信儿。今天不绕弯子,直接讲三种能落地的解法,都是我在实际环境里试过、管用的招儿。

先说第一种,也是最基础的——检查是否有阻塞进程。很多时候数据库显示“正在恢复”,不是真坏了,是有别的会话握着资源不放,把恢复线程给堵死了。你打开SQL Server Management Studio,跑一句,看看有没有返回结果。如果有,找到那个阻塞源头,用把它干掉,恢复进程往往就自己动起来了。我遇到过一次,就是个凌晨跑的报表任务没结束,把恢复卡了两小时,杀了进程三分钟就完事儿了。这招成本最低,先试它准没错。
要是没找到阻塞,那就得考虑第二种,也是最常见的原因——日志文件太大或者事务日志损坏导致恢复卡住。这时候别慌,先看看错误日志,,找有没有关于日志或者恢复的报错。如果是正常关库时没干净导致的重做,你等一等可能自己好,但要是卡了几个小时没动静,就得用强制恢复的招儿了。先把数据库设为单用户模式,,然后执行,再跑。注意,这操作会丢数据,但总比库永远打不开强。跑完再,数据库基本能回来。这招我用过不下五次,每次都能把库从悬崖边拉回来,但记住,能备份先备份,别拿生产库直接试。
第三种方法就得看情况了,如果你平时有做完整备份或者日志备份,那恢复就简单多了。直接找个维护窗口,把当前卡住的库删掉,然后从最近的备份做还原,选择模式,让SQLServer自己完成回滚和重做。但这里有个坑,很多人备份频率低,还原出来数据是昨天的,业务损失得自己扛。所以我建议,如果你用的是完整恢复模式,日志备份别停,哪怕一小时一次也行。我见过一个客户,卡了库直接还原到一周前,老板脸都绿了,后来他们改成每十五分钟做一次日志备份,再遇到这情况,顶多丢十五分钟数据。工具顺手了,恢复就是家常便饭。
聊到这儿,得说个容易被忽略的点——你服务器磁盘满了也会导致恢复卡住。别笑,我遇到过好几次,业务方天天催,结果一查磁盘,C盘就剩几百兆。SQLServer写日志需要空间,空间不够,恢复线程就挂那儿装死。你检查一下里日志文件的路径,再看看那个盘符的剩余空间,如果低于几百MB,赶紧清理临时文件或者加磁盘。清理完不用重启服务,恢复进程会自动继续。这招虽然不算常规解法,但胜在免费且立竿见影,比折腾半天数据库命令省心多了。
另外,还有一种情况容易让人误判,就是数据库在正常做大的事务回滚,比如有人跑了个删除千万行的操作,然后取消了。这时候恢复进程可能持续几十分钟甚至几个小时,状态一直显示“正在恢复”,其实它是真在干活,不是卡死。你可以查一下里的字段,看回滚进度。如果数值在动,耐心等就行;要是长时间卡在同一个百分比,那就用前面说的杀进程或者强制恢复。做这行,判断“它在忙”和“它死了”很重要,别一看到恢复就乱动,有时候动错了反而把库弄崩了。
说点实在的建议。数据库卡恢复这事儿,百分之八十都能靠上面三种方法解决,但真正的核心是预防。你平时得把备份策略做好,完整备份加日志备份,别偷懒;监控脚本也得配上,发现恢复时间超过阈值就自动报警。还有,定期检查数据库的设置,默认是CHECKSUM,这个能提前发现页损坏,别改成NONE,不然等真出问题就晚了。另外,版本别太老,SQLServer 2016以上的恢复机制比老版本强不少,特别是并行恢复和快速回滚的功能,能省掉你不少等待时间。
回到标题说的“三种解决方法”,其实核心就一句话:先看阻塞,再看日志,靠备份。真遇到卡恢复,别慌,按这个顺序排查,百分之八十的库能救回来。剩下那百分之二十,要么是硬件彻底坏了,要么是没备份只能认栽。但只要你平时把该做的做了,这问题基本不会找上你。干这行久了你会发现,数据库恢复不是技术活,是习惯活——你备份做得勤、监控做得细,它自然就老实。要是真卡住了,也别硬扛,动手试试上面说的招儿,大多数时候,几行命令就能把库从“正在恢复”拉回“在线”。


