干了十来年数据库运维,最怕半夜接到的电话就是“库挂了”。尤其是SQL Server 2012,这版本老归老,但企业里用的还真不少,稳定性其实还行,可一旦碰上断电、磁盘坏道或者强制杀进程,那“置疑”(Suspect)状态或者直接无法附加的破事就来了。今天不扯那些官方文档里绕来绕去的术语,就聊聊我实际处理SQL2012数据库损坏时,那些真正管用的修复路子,还有最容易让人栽跟头的坑。

先说句实在话,碰到数据库损坏,第一反应千万别是急着找修复工具。你得先判断这库到底能不能抢救,值不值得抢救。很多新手一看附加失败就慌,直接跑DBCC CHECKDB带REPAIRALLOWDATALOSS,结果数据是能打开了,但某些业务表里莫名其妙少了几行关键数据,那可比库打不开还麻烦。我的习惯是,先看一眼错误日志和Windows事件查看器,搞清楚是物理损坏(比如磁盘I/O报错)还是逻辑损坏(比如页校验失败)。如果是物理层问题,你修库之前得先修盘,否则修完还是坏,白忙活。
真要动手修,最常规的路子就是DBCC CHECKDB。但这里有个关键细节,很多人不知道:SQL2012的CHECKDB在检测到损坏时,会默认在数据库里创建一个叫“置疑”的紧急状态,这时候你得先把数据库切到单用户模式,再跑修复。具体命令不复杂,但顺序别搞反。先执行,强制踢掉所有连接,然后再跑。这个REPAIRREBUILD是只重建索引和结构,不丢数据,能不动数据就别动数据,这是底线。
但说句掏心窝的话,REPAIR_REBUILD只对非聚集索引损坏或者页分配错误有效。如果运气背,碰上了系统表损坏,比如sys.sysschobjs这种基础元数据出了问题,那CHECKDB八成会报错,根本修不动。这时候别死磕,赶紧评估一条备份的时间点。如果你的备份策略是完整备份加日志备份,那最稳妥的方案其实是把库恢复到损坏前最近的那个时间点,然后把损坏库里的差异数据用工具导出来,比如用SQL Server的导出数据向导或者第三方工具,尽量把业务影响降到最低。记住,修复是手段,备份才是王道,这话真不是口号。
还有个特别容易踩的坑,就是很多人喜欢用第三方工具,比如网上流传的“数据库修复大师”之类。不是说这些工具全没用,而是你得明白它们的原理。大多数这类工具是直接解析MDF文件的数据页,绕过SQL Server的日志和事务机制,把能读出来的表数据硬抠出来。好处是能在官方手段全失效的时候捞点数据出来,坏处是捞出来的数据可能没有完整性约束,外键关系全乱套,而且对文件大小和损坏程度很挑剔。我见过有人花大几千买了个工具,结果跑了一晚上,导出来的Excel表数据对不上账,还得靠手动对账,那叫一个酸爽。
再讲一个实战里特别容易忽略的点:修复之后的事务日志备份链。SQL2012默认是简单恢复模式,这种模式下日志备份是被禁用的,所以如果库在简单模式下损坏,你能恢复的粒度就只到上次完整备份或差异备份。但如果你用的是完整恢复模式,修复过程中会把事务日志标记为“损坏”,后续的日志备份会失败。这时候你必须在修复完成后立刻做一次完整的数据库备份,重新建立日志备份链,否则下次再出问题,你连恢复的起点都没有。这个细节,很多DBA都栽过跟头。
再提醒一个细节:修复时的系统资源占用。DBCC CHECKDB在跑的时候,尤其是大库,那CPU和磁盘I/O飙升得厉害,几乎能把生产环境拖死。所以如果不是紧急到必须在线处理,最好挑业务低峰期,或者直接把库切到离线模式修。另外,修复前务必把MDF和LDF文件做个物理备份,哪怕是用Windows复制粘贴到另一块盘上都行,这是个保命习惯。万一修复过程把文件搞得更烂,你至少还有原始底子可以再试其他办法。
说说预防吧。SQL201


