前天晚上十二点多,我正打算关电脑睡觉,手机突然响了。一个做电商的朋友声音都变了,说他们公司的SQL数据库卡在“正在还原”状态,整个后台都瘫痪了,订单都进不来。我问他是不是有人点了还原,他说下午确实有人动过数据库,但还原应该早结束了,现在这状态已经持续了快五个小时。

这种情况我见过太多了。SQL数据库卡在还原状态,说大不大,但处理不好就是事故。其实大多数情况下,数据库本身没坏,就是进程卡住了,或者锁没释放。你先别急着重启服务器,那是最笨的办法,搞不好把好好的数据搞出毛病来。我教你这五个步骤,按顺序来,基本都能解决。
第一步,你得先确认到底有没有还原任务在跑。打开SQL Server Management Studio,右键点击那个卡住的数据库,看属性里的状态是什么。如果显示“还原中”,那就打开查询窗口,执行一句:。如果结果里有记录,说明真在还原,那你就得等,千万别手贱去KILL进程。如果结果是空的,那就是假象,问题出在别处。
第二步,查一下是不是有死锁。很多时候数据库卡在还原状态,是因为有一个之前没跑完的事务还占着锁。你执行,看看有没有进程的BLK列不为空。如果有,那就是有阻塞。你找到那个阻塞的SPID,然后看它是啥操作,如果确定是残留的查询或者会话,可以直接。但记住,KILL之前最好确认一下那个进程不是核心业务,不然会影响线上。
第三步,如果上面都查不到问题,那就得用“偷偷还原”的办法了。这个方法是让SQL Server把当前卡住的还原先结束掉,具体操作是:。注意,这句命令的执行结果有两种,如果它成功跑完了,数据库状态会变成“正常”,你就能用了。但如果它报错说“有一个或多个进程正在使用数据库”,那就说明还有连接占着,你得先断开所有连接。
第四步,断开连接得用“狠”一点的方式。执行,这句话会把所有连着的会话强制踢掉,注意是强制,会回滚所有未提交事务。然后你再把它拉起来:。这时候再查状态,一般就恢复正常了。这个方法我用了好多次,在测试环境随便搞,生产环境你得在业务低峰期操作,并且提前跟开发说一声,不然别人查库查不了会骂死你。
第五步,如果上面所有方法都没用,那就是数据库文件本身出问题了。这时候你要检查那个还原的备份文件是不是完整的,有时候网络传输中断或者磁盘满了,备份文件是残缺的。你去看一下SQL Server的错误日志,路径一般在安装目录下的,搜“RESTORE”相关的报错。如果日志里写了“Backup file is corrupted”,那就别折腾了,直接拿最新的完整备份加日志备份重新还原,这次记得选“WITH REPLACE”覆盖掉那个损坏的还原状态。
我有个习惯,处理这种问题之前,先看一眼磁盘空间。真的,好几次我排查半天,发现是C盘满了,还原进程写不了日志,就一直卡在那。你执行看看剩余空间,如果某个盘快满了,先清理临时文件或者日志文件,再回头执行第三步的,问题迎刃而解。
还有一个容易被忽略的,就是SQL Server服务账号的权限。如果你的服务账号对备份文件所在的文件夹没有读权限,还原也会一直挂着。这情况多见于把备份放在共享盘或者别的服务器上。你检查一下服务账号是不是本地系统,如果是,那就用管理员身份跑一下,或者临时把备份文件复制到本地再还原。
说到这,我得提醒你,那种“正在还原”的状态其实是个保护机制,说明SQL Server还没把数据页写完,你强行去动它反而容易搞出逻辑损坏。所以我的建议是,每一步操作之间,隔个一二十秒,让系统喘口气,别急着一口气全执行完。另外,如果你用的是AlwaysOn可用性组,那情况更复杂一点,得从副本那边看同步状态,别在主库上瞎折腾。
说个很多人不知道的小技巧:你可以在SSMS里右键那个卡住的数据库,选“任务”->“还原”->“数据库”,然后随便选一个备份文件,勾选“选项”里的“覆盖现有数据库”,执行一次完整的还原操作。这一步看着像多此一举,其实它会强制清掉之前那个卡住的还原会话,数据库状态会重新计算。我遇到过几次,就这么一搞,状态立马变正常了。
回到我朋友那个案例,我远程帮他连上服务器,第一步查了没有正在跑的还原任务,第二步发现有个残留的会话占着锁,KILL掉之后执行了,数据库十秒内就恢复正常了。他后来跟我说,早知道这么简单就不慌那五个小时了。其实这种事,慌没用,按步骤来,大部分都是小问题。你把这五个步骤存下来,下次遇到,五分钟之内就能搞定。


