数据库损坏怎么修复
数据库损坏,数据我见过最惨的库损一次是银行核心系统。凌晨三点,坏修值班同事打电话说交易表全打不开了。数据赶到机房,库损屏幕上一片红字——那感觉就像看自己的坏修心脏监护仪报警。
先说结论:能修,数据但别指望奇迹。库损大部分损坏其实是坏修逻辑损坏,物理损坏基本没救。数据区分这两者很简单:如果数据库能启动但报错,库损大概率是坏修逻辑问题;如果连文件都读不出来,那基本是数据硬盘物理故障,别浪费时间了。库损
逻辑损坏最常见的坏修场景是突然断电。你正写着数据,啪,电没了。写入了一半的事务留在磁盘上,文件系统认为它完整,但数据库引擎发现日志和实际数据对不上。这时候别慌,先别启动数据库,直接做冷备份,把整个数据目录复制走。然后尝试用官方工具做恢复——MySQL有innodb_force_recovery参数,PostgreSQL有pg_resetwal,SQL Server有DBCC CHECKDB。这些工具的原理都类似:跳过损坏页,重建索引,回滚未完成事务。
我有个朋友,他公司的数据库被误删了表,不是drop table,是rm了物理文件。他当时第一个反应是重启服务,结果文件句柄释放了,数据彻底没了。正确做法是什么都不做,立刻停掉所有写操作,用lsof查看还有没有进程持有已删除文件的句柄,如果有,从/proc目录把文件内容拷出来。那次他运气好,赶在进程崩溃前抢救回来大部分数据。
但说实话,这些手段都是亡羊补牢。真正靠谱的修复方案只有一个:备份。不是那种每周一次的备份,是每天、每小时的增量备份,加上实时的binlog或WAL归档。我见过太多小公司,数据库跑了两三年,从来没做过恢复演练。真出事那天,发现备份文件是坏的,或者备份策略漏了某个关键库,那时候哭都来不及。
有一次帮一个电商客户处理问题,他的数据库是因为磁盘满了导致写入失败,然后某个服务强行kill了进程,结果数据文件头损坏了。我们尝试了各种修复工具,最后发现有一个表的数据页已经完全被覆盖,只能恢复到前一天晚上的备份,丢失了大概6小时的数据。老板气得拍桌子,但没办法——谁让你不配SSD,不监控磁盘空间呢。
还有一个容易被忽略的点:数据库版本升级也可能导致损坏。有个客户从MySQL 5.6直接跳到8.0,没走中间版本,结果字符集排序规则全乱了,索引全部失效。这种问题不是数据坏了,是元数据不兼容。解决办法是先dump成SQL文件,再导入新版本,别直接拿旧文件启动新程序。
说到底,修复数据库是门手艺活,得懂得看错误日志,理解事务日志的机制,甚至会用十六进制编辑器去翻文件头。但更重要的,是平时把备份和监控做好。我自己的原则是:任何数据库,如果连续三天没有成功备份,我晚上就睡不踏实。这不是什么高科技,纯粹是被吓出来的习惯。
最后说一个反直觉的事实:有时候,什么都不做就是最好的修复。如果数据库启动时报错,但只是某个辅助索引损坏,而你有足够时间重建它,那就别急着跑修复工具——很多工具在修复过程中会锁表,反而扩大故障范围。先评估损坏范围,再决定方案。修复之前,永远先备份那个损坏的文件。这话我说了一百遍,但每次还是有人跳过这一步,然后哭着回来问怎么恢复被修复工具搞得更坏的数据。
数据库这东西,平时安安静静待在那儿,一坏就是大事。修不修得好,一半靠技术,一半靠你之前有没有做足功课。