半夜两点,电话响了。运维同事的声音有点发抖:“MySQL的data目录空了,show tables全是空,备份还在,但那是昨天凌晨的。”这种场景,凡是跟数据库打过交道的人,都做过噩梦。数据文件丢失这事儿,它不像服务器宕机那样给你个明确的报错,而是那种“文件还在,但数据没了”的诡异状态,最磨人。今天这篇,不聊理论,就聊我踩过坑之后总结出来的三步急救流程,每一步都是拿真金白银换来的教训。

第一步,别急着重启,先冻结现场。很多人一看数据没了,第一反应是重启MySQL,或者干脆把磁盘重新挂载一遍。这是最致命的错误。你得把当前的文件系统状态当成犯罪现场,任何写操作都是破坏证据。先做的应该是把MySQL服务停掉,注意是停掉,不是重启,用或者,确保没有进程在往磁盘里写东西。然后立刻用看看有没有进程还握着已删除文件的句柄,特别是mysqld进程。如果发现mysqld还开着那些被删除的.ibd文件,恭喜你,胜算大了三成,因为Linux下只要进程还持有文件句柄,数据就还有救,直接就能把文件抠出来。这一步做完,再去检查磁盘分区,用和确认是不是挂载点出了问题,有时候只是文件系统没挂上,虚惊一场。
第二步,根据现场情况选恢复策略。这里分三种情况。第一种,表结构还在,只是数据文件(.ibd)没了,但你有文件或者里还能看到表定义,这种最简单,直接,然后把备份里的.ibd拷回来,再,十秒钟搞定。第二种,整个data目录都没了,但你有物理备份(比如Percona XtraBackup的全量+增量),那别犹豫,赶紧找个干净环境搭建恢复实例,用重放redo log,把数据恢复到备份时间点,然后想办法追binlog。第三种最惨,啥备份都没有,只有磁盘上的二进制残留。这时候别瞎折腾,先试试或者这类工具扫磁盘,运气好能捞回来一些碎片,但别抱太大。
这里要特别提醒一句,很多人忽略binlog的价值。只要binlog还在,哪怕数据文件全碎了,你也能把数据恢复到一秒。前提是你开了,而且binlog没跟data目录放在同一块盘上。我见过太多人把binlog和数据文件放在一起,磁盘一炸,全完。所以,恢复的第二步,先确认binlog的完整性和位置,用解析出的操作记录,这就等于有了时间机器。
第三步,也是最考验功力的,拼表。如果你通过extundelete或者文件句柄恢复出来一堆.ibd文件,但innodb的字典表里已经没有这些表的信息了,怎么把数据导出来?这时候得用工具,它能把.ibd文件里的表结构定义(SDI信息)导出来。拿到SDI之后,你还要处理表空间ID不一致的问题。innodb有个硬性要求,表空间ID必须匹配,不然直接会报错。解决办法是,先创建一个同结构的表,记下它的表空间ID,然后用修改.ibd文件头部的表空间ID字段,改成目标值。这个操作有点脏,但确实管用。改完之后,用导入,大概率能成。
如果连.ibd文件都是碎的,那就得走极端路线了。用命令从裸设备或者残留文件里提取文本数据,这种办法适合数据表是纯文本类型(比如varchar、text)的情况,数字和日期也能凑合,但二进制字段基本没戏。提取出来的数据是乱序的,你得靠主键或者唯一索引的值去重、排序,这个过程纯手工,极其痛苦,但总比数据全没了强。
整个恢复过程,最忌讳的是病急乱投医。我见过有人从网上下载一堆“数据恢复工具”,挨个试,结果把磁盘搞得更乱。正确的做法是,所有恢复操作都在副本上做,原始磁盘只读挂载。你可以用把整个分区做成镜像文件,然后在镜像上操作。这一步虽然耗时,但能保证原始数据不被二次破坏。要知道,数据恢复的黄金法则就是“别在原盘上折腾”。
再说一个很多人不知道的细节:MySQL的redo log(iblogfile0, iblogfile1)和undo log,在数据文件丢失时也能救命。如果redo log还完整,你可以尝试用参数把MySQL启动到恢复模式,设置(注意从1到6逐级试,能启动到哪个级别算哪个级别),然后通过导出数据。这个方法的原理是,MySQL在启动时会自动重放redo log,把崩溃前没来得及写入数据文件的操作补上。虽然数据文件没了,但redo log里的记录足以重建出不少数据。不过要提醒你,级别越高,能启动的概率越大,但数据一致性越差,导出的数据可能有缺失或重复,需要后期清理。
这次劫后余生之后,你得做三件事。第一,把和都设成1,性能损耗可以接受,但数据安全是最底线。第二,备份策略要分级,物理备份(XtraBackup)一天一次,binlog实时传输到异地,核心表单独的mysqldump一天四次。第三,也是最重要的,定期做恢复演练。别只检查备份文件能不能打开,要真的在测试环境里把备份恢复一遍,确认数据能查、能写、能跑业务。很多公司备份做了三年,第一次真出事才发现备份是坏的,这种教训太贵了。
数据文件丢失这事儿,说到底是概率问题,但恢复成功与否,是准备问题。三步走下来,能救回来大部分场景。但记住,最好的恢复,是根本用不着恢复。把备份当回事儿,把binlog当回事儿,把演练当回事儿,你才能在半夜接到电话时,冷静地说一句:“别慌,按流程走。”


