数据库卡死这事儿,干运维的兄弟十有八九都撞见过。尤其是SQL Server 2012,系统跑着跑着,突然弹个“恢复挂起”,整个库就像被人掐住脖子,查询堵死,应用报错,老板在身后转悠,那种滋味,真比吃苍蝇还难受。我见过不少同行,一遇到这情况就慌了神,直接重启服务,结果数据没恢复,反而把日志搞得更乱,只能翻备份重做,一晚上白干。其实“恢复挂起”不是绝症,它只是SQL Server在启动或恢复过程中,某个环节卡住了,没走下去。你只要摸清它的脾气,按步骤来,大部分情况都能救回来。

先说说这毛病到底咋来的。2012这版本,恢复机制跟老版本不太一样,它默认启用了“加速恢复”和“间接检查点”,好处是故障转移快,坏处是——一旦日志文件膨胀得厉害,或者磁盘I/O跟不上,恢复进程就会卡在某个阶段,既不前进也不报错,就挂在那儿。还有一种常见情况,是你手动把数据库设为“脱机”或者“只读”,但事务没提交完,系统内部还在等锁,结果状态就僵住了。很多新手一查,看到状态是“恢复挂起”,以为数据全完了,其实那只是元数据层面的标记,数据文件本身还好好的。
第一步,别急着动刀,先看日志。打开SQL Server错误日志,或者Windows事件查看器里的应用程序日志,找那个时间段前后的记录。你会看到类似“数据库XXX的恢复操作正在等待”或者“等待缓冲区闩锁”之类的提示。这一步特别关键,因为它能告诉你卡在哪儿——是日志文件满了,还是某个会话占着资源不放,还是磁盘空间不够了。我见过最坑的一次,是某台服务器C盘只剩200MB,日志文件疯狂增长,恢复进程写不进去,就挂那儿了。你要是不看日志,直接去杀进程,杀完人家又自动重启,继续卡,白费劲。
第二步,查会话和锁。跑一条或者查,看有没有哪个SPID在等待恢复进程完成。很多时候,是你自己或者某个应用程序开了一个长事务,一直不提交,SQL Server为了保一致性,必须等它结束才能继续恢复。这种时候,你得判断这个事务能不能杀。如果是对应某个死掉的连接,直接掉那个SPID,恢复进程就会继续走。但要注意,如果是核心业务在跑,你得先跟开发确认,别一刀切下去,把正在跑的大批量更新给砍了,那损失可比卡死还大。
第三步,也是最核心的一步,就是手动干预恢复状态。如果日志确认没问题,锁也清了,它还是挂起,那就得用,再,然后跑修复。这个操作相当于把数据库强行拉起来,让它进入应急模式,允许你检查物理完整性。跑完,如果只是逻辑损坏,它会自动修复;如果修复不了,会提示你哪些页坏了,你还能从备份里抽那些页出来。再,恢复正常访问。整个过程看着简单,但每一步都要等,别急,尤其在数据量大时,跑几个小时都正常。
这里头有个坑,我必须提醒你:别一上来就做第三步。我见过有人跳过日志和锁检查,直接进应急模式,结果把本来还能正常读写的库,搞成了只能单用户访问,业务全停,比之前更惨。应急模式是把双刃剑,它能救命,也能伤人。只有当你确认前两步都没问题,或者错误日志里明确告诉你“文件损坏”或“分配错误”时,才值得动这一步。另外,跑之前,最好先做个文件级别的备份,哪怕只拷一份MDF和LDF出来,心里也踏实。
说到备份,这其实是预防“恢复挂起”最实在的手段。2012这版本,很多挂起案例都是日志文件无限增长惹的祸——你设置了“简单”恢复模式,但它内部还是会写日志,只是不保留。一旦某个检查点没跑完,日志文件就会疯长,直到占满磁盘。所以,日常维护里,定期收缩日志、监控磁盘空间、设置合理的自动增长比例,比啥都管用。别等到卡死了才想起来,那会儿你连备份都难做。
还有个容易被忽略的点,就是补丁。SQL Server 2012已经停止主流支持了,但微软还是发了不少关键更新,尤其针对恢复机制的修复。你要是还在用SP1甚至RTM版本,那出问题的概率比SP4高好几倍。我建议你至少打到SP4,再装最新的累积更新。别嫌麻烦,这些补丁里就藏着针对“恢复挂起”的修复,打了之后,很多老毛病自己就消失了。
说句掏心窝子的话,数据库卡死这事儿,七分靠预防,三分靠处理。你把日志、锁、磁盘这三样盯紧了,大部分挂起都能绕过去。真遇上了,也别慌,就按我说的三步走——先看日志定方向,再查会话清障碍,才动应急模式。每一步都留证据,每一步都做备份,实在不行,还能从备份里恢复。这行干久了你就明白,数据库出问题不可怕,可怕的是你乱操作,把小问题整成大事故。


