干这行久了,你会发现一个挺扎心的事实:不少程序员或者运维,数据库玩得贼溜,写起SQL来行云流水,但真到了要从一个.sql文件里把数据捞回来的时候,反而会卡壳。倒不是不会敲那行,而是他们太依赖图形化工具了,鼠标一点,导入完成,皆大欢喜。可一旦文件大点,比如几个G,或者线上环境不允许你装Navicat,又或者服务器上只有命令行,这时候,手忙脚乱的样子就藏不住了。今天咱们不聊那些高深的架构,就纯粹掰扯掰扯,怎么把一个.sql文件,干净利落地恢复到你的MySQL里。

很多人第一步就栽在字符集上。你辛辛苦苦从线上导出的文件,可能带着的编码,也可能带着的老古董编码。直接一股脑儿丢进去,轻则中文变问号,重则直接报错中断,前面导入的几万条数据全白费。所以,动手前先花十秒钟,用瞄一眼文件头,看看有没有或者之类的字样。要是没有,你最好在导入命令里显式指定一下,比如。这一个小习惯,能帮你挡掉后面百分之八十的乱码麻烦。
接下来是库的选择。有些新手喜欢直接,也不管里面有没有语句,结果就是数据全跑到默认的test库或者干脆报错说表不存在。稳妥的做法是,先看文件里有没有建库语句。如果有,那你就老老实实先建一个空库,然后导入的时候指定这个库名。如果没有,那就更简单了,,然后再导入。这里有个小技巧,导入前先把SQL文件里的语句过一遍脑子——别怕,这是好事,说明这个备份是干净的,不会跟现有表结构冲突。但如果你的目标是恢复到一个已经跑着业务的库里,想合并数据,那就得小心了,最好先备份现有数据再操作。
真正让人头疼的是大文件。一个几百兆甚至几个G的SQL文件,用命令行直接导入,那个进度条你是看不见的,屏幕就卡在那儿,你不知道它是在干活还是死机了。这时候别干等,教你两招。第一,用命令,,这玩意儿能显示实时进度和速度,心里有底多了。第二,如果实在没有pv,那就用挂后台跑,,然后隔一会儿看一眼日志大小有没有变化。千万别傻乎乎地开着终端盯着,万一断网或者不小心关了窗口,导入进程挂了,你哭都来不及。
还有一种情况,文件里混着存储过程、触发器或者函数。这类对象在导入时往往伴随着的切换。如果你发现导入老是报错,卡在某个上,多半是没处理。解决办法很简单,在命令行里先执行,然后,再切回来。或者更省事,直接用客户端的命令,它能自动处理大部分这类情况。不过我还是建议,遇到这种文件,先单独把存储过程部分拆出来跑,别跟表数据混在一起,出问题也好排查。
导入完了,别急着欢呼,验证这一步不能省。很多人导入完就关机走人,第二天业务一跑,发现某个表的数据对不上,或者主键冲突,再回头查,发现当时导入日志里其实有一堆的记录,只是被刷屏刷过去了。所以导入过程中,最好把输出重定向到日志文件,导入完用扫一遍。有报错不可怕,关键是得知道错在哪几行。这时候就可以用查看出错位置的上下文,手动修复那几条坏数据,单独再补一次导入。
另外,如果你手里是个压缩包,比如,那就别傻乎乎解压了再导。直接一条命令搞定:。这样既省磁盘空间,又省了解压时间,管道流式处理,内存占用也小。这招在服务器磁盘特别紧张的时候,简直是救命稻草。我见过有人为了导入一个5G的压缩包,先解压出20G的临时文件,结果磁盘满了,导入失败,数据还丢了,那叫一个惨。
还有一类坑,是权限问题。你用的是root账号,但线上环境可能只给你一个普通账号,只有部分库的权限。这时候导入前先确认一下,,看看有没有、、这些权限。没有的话,要么找管理员开权限,要么就只能让管理员帮你导。千万别硬试,报错报得你怀疑人生,发现是权限不够,那纯属浪费时间。
想多说一句,恢复SQL文件这事儿,看着像个糙活,但真出问题的时候,最考验基本功。那些整天吹嘘自己会什么大数据平台、分布式架构的人,你让他手工恢复一个几百兆的备份,他可能手忙脚乱。反倒是那些平时闷不吭声,能把一个导出、导入玩得明明白白的人,才是真正让人放心的。所以,别嫌命令行土,关键时候,它比花里胡哨的界面可靠得多。下次再遇到的需求,别慌,按着上面这几步走,稳得一批。


