这事儿我估计干这行的都遇到过,数据库不小心删了,那一瞬间脑子嗡的一声,血压直接飙到180。我有个朋友,前两年在一家小公司当 DBA,半夜两点多手滑把生产库的表给 DROP 了,当时整个人从椅子上弹起来,咖啡洒了一键盘。他后来跟我形容那个感觉,就像开车在高速上突然发现刹车没了,只能硬着头皮往前冲。其实数据库删除这事,分好几种情况:有的人误删了一条数据,有的把整个表给 TRUNCATE 了,还有更狠的直接把数据库文件给 rm 掉。不同场景下,恢复的逻辑和难度天差地别,但有一点是共通的——千万别慌,越慌越容易二次破坏。

先说最基础也最常见的场景,误删单条或几条数据。这时候如果你用的是 MySQL,而且开启了 binlog,基本不用太紧张。binlog 说白了就是操作日志,把每一次修改都记下来。删除操作也会被记录成 DELETE 语句,只要你没把 binlog 文件删了,就能通过 mysqlbinlog 把删除前的数据捞回来。具体操作也不复杂:先找到删除发生时间点附近的 binlog,然后用 mysqlbinlog 解析成 SQL,grep 出那个 DELETE 语句,再把它反向转成 INSERT 就行。但这里有个坑,binlog 默认会定期清理,如果 expirelogsdays 设置得太短(比如只有 3 天),过了时间就真的找不回来了。所以平时要把这个参数调大,至少保留一两周的缓冲期。
再说更严重的情况,整个表被 TRUNCATE 或 DROP 了。TRUNCATE 和 DELETE 不一样,DELETE 是逐条删,仍能在 binlog 里找到痕迹;TRUNCATE 则直接清空表的物理文件,binlog 只会记录一条 TRUNCATE 语句,不会记录每一行数据。这时单靠 binlog 没戏,只能依赖备份。很多公司都有自己的备份策略,比如每天凌晨全量备份、每小时增量备份。恢复时,先把最近一次的全量备份恢复出来,然后回放从那次备份到 TRUNCATE 之前的增量 binlog,这样就能把数据恢复到删除前的状态。恢复过程对时间窗口要求很高,需要精准定位 TRUNCATE 发生的时间点,回放 binlog 时要在该时间点前停住,否则恢复出来的数据又会被再次 TRUNCATE。
还有一种更惨的情况,就是直接把数据库的物理文件删了,比如 rm -rf data 目录。这种操作在 Linux 服务器上屡见不鲜,尤其是手速快过脑子的运维。好消息是,Linux 的文件删除机制有个特性——只要文件仍被进程占用,即使从目录里删掉,inode 仍在,数据块也未被真正覆盖。这时赶紧停止对该目录的所有写操作,用 lsof 找到被删除但仍被占用的文件描述符,再通过 /proc 文件系统把它拷贝出来。我有个同行就经历过,他删了 MySQL 的 ibdata1 文件,吓得脸都白了,但 MySQL 进程还在跑,及时用 lsof 找到描述符,成功把文件拷回来了。整个过程像侦探破案,每一步都要小心翼翼。
但现实往往比剧本更残酷。很多小公司根本没有备份,也没有开启 binlog,甚至文件系统是没有开启日志的 ext4。这种情况下恢复基本只能靠运气。市面上有一些数据恢复工具,如 extundelete、testdisk、photorec,它们扫描磁盘空闲空间,尝试找回被删除的 inode。成功率完全取决于删除后是否有新的数据写入。如果删除后立刻停止所有写操作,仍有可能找回一部分;但如果继续往数据库写入,新数据会很快覆盖被删除的块,恢复几乎不可能。所以遇到这种情况,第一时间要断电或强制挂载为只读,防止任何进程继续写入磁盘。
说到这里,我得提一下云数据库用户的心态。很多人觉得把数据库放在云上就万事大吉,比如使用阿里云 RDS、腾讯云 CDB 等托管服务。但云厂商并不是慈善机构,他们保证的是数据库的可用性,而不是手贱删了数据还能免费恢复。有些云服务会自动备份,但备份周期和保留时间都有限制,例如默认只保留 7 天,超过后就会自动清理。而且恢复本身也有时间成本,几 TB 的数据库可能需要好几个小时。更坑的是,有的云厂商的恢复是按次数收费的,一次恢复几百块,恢复几次的费用甚至比买新数据库还贵。所以千万别以为云上就高枕无忧,自己必须做好备份策略。
还有一种被很多人忽略的场景,就是误操作发生在主从同步架构里。你在主库上删了数据,从库会通过 binlog 自动同步这个删除操作,结果从库的数据也没了。如果有延迟从库(比如延迟一小时),还有机会从延迟从库里把数据捞出来。但大多数公司的从库都是实时同步的,主库删了,从库瞬间跟着删。经验丰富的 DBA 会专门建一个延迟从库,把同步延迟设为几个小时,这样主库出问题时,延迟从库里仍保存着删除前的数据。成本不高,却能在关键时刻救命。我认识的老 DBA 手底下所有数据库都配了延迟从库,哪怕公司觉得浪费资源,他也坚持这么做。后来真出事时,整个公司都感谢他。
我想说,数据库恢复这事儿,技术手段再多,也不如预防做好。很多人是出了事才开始研究恢复方法,但那时往往已经晚了。靠谱的做法是平时就把备份策略落到实处,并定期演练恢复。很多公司虽然做了备份,却从未验证过备份能否使用,结果真出事时发现备份文件早已损坏,那才叫欲哭无泪。另外,权限管理也很重要,把 DROP、TRUNCATE 等高危操作的权限收回,只给少数人,甚至通过脚本或自动化平台执行,从源头上降低误操作概率。数据库删除不可怕,可怕的是没有准备。你永远不知道手滑的那一秒什么时候会来,但你可以决定在那之前是否已经做好了兜底的准备。


