前几天一个做电商的朋友半夜给我打电话,声音都变了:“数据库崩了,用户订单全没了,怎么办?”挂了电话我远程帮他看了看,好在只是误删了一张表,用binlog日志恢复了回来。他长舒一口气,说以后再也不手贱了。其实这种事在圈子里太常见了,MySQL数据库跑得好好的,一个不小心,数据就没了。删库跑路虽然是玩笑话,但真遇上数据丢失,哭都来不及。

很多人觉得恢复数据库是件特别高深的事,得找技术大牛来搞。其实不然,MySQL自带的工具加上几个常用技巧,完全能自己搞定。只要你别在慌乱中乱敲命令,恢复的成功率很高。今天我就把三种最实用的恢复方法掰开揉碎讲给你听。第一种是用全量备份加binlog日志恢复,这是最稳妥的方式。第二种是用MySQL自带的mysqlbinlog工具,适合误操作后的快速回滚。第三种是用第三方工具比如Percona Data Recovery,专门对付那些连表结构都损坏了的情况。
先说说全量备份加binlog这个组合拳。很多公司为了省事,只做全量备份,比如每天凌晨导出一份SQL文件。这确实能兜底,但有个致命缺陷:如果你在下午三点误删了表,恢复的时候只能恢复到凌晨那个时间点,中间十几个小时的数据全没了。所以必须搭配binlog日志,它记录了所有对数据库的修改操作。恢复流程很简单:先拿全量备份建一个临时库,然后用mysqlbinlog工具把从备份时间点到出问题时间点之间的binlog日志重放一遍。这样一来,数据就能恢复到最接近出事那一刻的状态。
具体操作时,你得先确认binlog日志是开启状态。登录MySQL后用检查,如果显示ON那就万事大吉。如果没开,那从今天起必须打开。修改配置文件,加上和,前者开启日志记录,后者设置保留7天的日志,既不会占用太多磁盘空间,又能保证有足够的时间窗口来恢复。很多新手栽就栽在连binlog都没开,出了事只能干瞪眼。
第二种方法专门对付那些误删除或者误更新的情况。比如你刚执行了一个,结果发现条件写错了,删掉了不该删的数据。这时候别慌,也别急着重启数据库。先找到出问题的时间点,然后用mysqlbinlog工具把那个时间点前后的日志解析出来,找到那条错误的DELETE语句。接着用这个命令,就能把误操作之前的正常数据恢复回来。
这里有个坑必须提醒你:binlog日志文件是按序号递增的,比如mysql-bin.001、mysql-bin.002这样。恢复的时候要用参数指定时间范围,而不是直接去猜哪个文件。因为binlog会滚动,如果你只恢复了一个文件,可能漏掉其他文件里的操作。正确做法是先通过把所有相关日志合并输出,再定位到具体时间点。我见过有人只恢复了一个文件,结果发现数据还是丢了小部分,就是因为没把日志合并全。
第三种方法对付的是最棘手的情况:表结构损坏,或者连binlog日志都丢了。比如硬盘坏了、文件系统崩溃,或者被人恶意删除了数据文件。这时候用常规方法已经没救了,得靠专业工具。Percona Data Recovery是业内比较靠谱的免费工具,它能直接扫描MySQL的数据文件,把那些还能读出来的记录提取出来。原理是MySQL的数据文件虽然是二进制的,但数据记录有自己的固定格式,只要文件碎片没有被完全覆盖,工具就能像拼图一样把数据拼回来。
用这个工具需要点耐心。先下载Percona Data Recovery的源码,编译安装。然后执行指定你的数据目录,比如。工具会扫描所有.ibd文件,也就是InnoDB的数据文件。整个过程可能持续几个小时,取决于数据量大小。扫描完成后,它会生成一个SQL文件,里面包含了所有能恢复的数据。这时候你新建一个数据库,导入这个SQL文件就行。虽然不能保证100%恢复,但大部分情况下能找回九成以上的数据。
不过提醒一句:数据文件损坏后,第一时间要做的是备份原文件,而不是直接去跑恢复工具。很多人一着急,直接在损坏的数据文件上操作,结果把仅存的结构也破坏了。正确做法是先,把整个数据目录复制一份,然后用备份文件去跑恢复工具。原文件留着当救命稻草,万一恢复失败还能换个方法再试。
说几个日常防范的小习惯。第一,备份文件不要和数据库放在同一个服务器上,否则服务器崩了,备份也跟着没了。第二,定期测试恢复流程,别等到出事才发现备份文件是坏的。我见过最夸张的一个案例,某公司每天备份,但从来没验证过,结果数据库出事后,发现备份文件里有一半的表都是空的,因为备份脚本配置错了。第三,权限管理要严格,别让所有人都能执行DROP TABLE或者DROP DATABASE这类危险操作。建一个专门的管理账号,只有运维人员才能用。
数据安全这件事,说到底就是四个字:有备无患。MySQL恢复数据库的方法再多,都不如平时多做几手准备。今天讲的这三种方法,第一种是常规操作,第二种是紧急补救,第三种是兜底。你只要掌握了,哪怕真遇上数据丢失,也能从容应对。毕竟数据就是你的身家性命,多花点心思保护好它,比什么都强。


