干了十来年运维,数据库迁移这事儿,我闭着眼都能数出七八种工具。但轮到真要动手,或者半夜被电话叫起来处理故障时,我第一个摸到的,还是mysqldump。这玩意儿老,老得像我抽屉里那把生锈的瑞士军刀,但关键时刻,它比那些花里胡哨的电动工具更让我心里踏实。今天不聊那些云上的一键迁移,也不聊Percona XtraBackup的物理备份,就单纯聊聊,怎么用这把老刀,把数据从一个库房,稳稳当当地挪到另一个库房。

你先别急着敲命令,第一步不是连库,是看清楚你要搬的是什么。MySQL里那点门道,表结构、数据、触发器、存储过程、事件,还有视图,各有各的脾气。很多人栽跟头,就栽在以为一个就完事了。你想想,你搬家的时候,光把衣柜和床搬过去,墙上挂的画、抽屉里的螺丝刀、床底下的旧箱子就不管了?那叫搬家吗?那叫扔东西。数据库也一样,你光导个表结构和数据,回头应用一跑,报错说找不到存储过程,或者触发器没生效,你哭都来不及。所以,迁移前的第一件事,是盘点。用、、这些命令,把库里所有“非表”对象列个清单,心里有个数,待会儿dump的时候,参数该怎么加,你就门儿清了。
盘完了货,咱们再来谈参数。的参数多如牛毛,但真正要命的,其实就那几个。很多新手喜欢用,这没错,对于InnoDB表,它能保证一致性快照,不锁表,在线迁移的好帮手。但你得留个心眼,如果库里混着MyISAM表,这参数就失灵了,它会退化成全局锁表,业务直接卡死。你想想,凌晨两点,你一个下去,前台收银系统全卡住,那场面,比恐怖片还刺激。所以,我一般习惯加上再配合,同时先查一下,看看有没有非InnoDB的表,如果有,就得单独处理,或者干脆跟业务方商量个维护窗口,用配合全局锁,虽然会短暂锁表,但至少不会锁到天荒地老。
说到,这是个宝藏参数,但也是个坑。它会在dump文件里注释掉一行的信息,记录下当时的binlog位置。好处是,你导入数据后,如果想搭建从库,或者做增量同步,这行注释就是你的指路明灯。坏处是,如果你是在一个从库上执行dump,用了这个参数,它会记录从库自己的binlog位置,而不是主库的,你拿这个文件去搭建新从库,数据同步就会错位,差之毫厘,谬以千里。所以我自己的习惯是,如果只是单纯迁移数据到新环境,不用管主从,我压根不加这个参数;如果是为了搭建从库,我一定会在主库上跑dump,并且加上(新版本MySQL的写法),确保记录的是主库的坐标。
再来说说导入那头的坑,这是新手重灾区。拿到一个几百兆甚至几个G的SQL文件,直接一梭子下去,坐等结果。等来的可能是一屏幕的ERROR,或者干脆卡死不动。原因很简单,目标库的、字符集、甚至大小,可能跟源库不一致。你dump出来的SQL里,如果带着,但目标库的是latin1,那中文数据导入进去,出来全是一堆问号,你还没法骂街,因为没报错,就是数据错了。所以,导入之前,先去目标库执行一下,然后,再检查一下,最好跟源库保持一致。这一步,能帮你挡掉80%的灵异事件。
还有个大坑,是权限。你dump的时候,用的可能是root账号,但导入到新库,目标库可能没有那个账号,或者账号密码不一样。更恶心的是,如果dump文件里包含了和语句,你在导入时如果权限不够,会直接报错中断。所以,我的做法是,dump的时候,只导数据定义和数据,不导权限。具体来说,就是加(不创建数据库)和(导入后刷新权限),但更重要的是,提前在目标库手动建好用户,并授予对应权限。这样,导入的时候,SQL文件里就不会有那些需要超级权限才能执行的语句,整个过程干净利落。
数据导完了,你以为就万事大吉了?差得远。真正的考验在导入之后。你得做个“数据对账”。不是简单数一下行数,因为行数一样不代表数据一样。我通常会写几个简单的SQL,比如对比一下,再随机抽几条关键数据,看看字段值是否一致。更严谨一点,可以用命令,计算表的校验和,如果源库和目标库的校验和一致,那基本可以断定数据没问题了。这一步,千万别省,省了这一步,后面上线出问题,你连甩锅的底气都没有。
还得聊聊性能这回事。迁移几十个G的数据,用默认的,那速度慢得能让你怀疑人生。这时候,可以祭出参数,在dump和导入时压缩传输,能快不少。还有参数,避免一次性加载到内存,对于大表特别有用。另外,导入的时候,可以试试配合,牺牲一点安全性,换取导入速度的成倍提升。但记住,这只是迁移期间的临时参数,导完之后一定要改回来,否则数据安全就没了保障。
说这么多,不是想吓唬你,而是想告诉你,mysqldump这工具,看着简单,用好了是神器,用不好就是定时炸弹。它就像一把老式手动挡的车,起步慢,操作繁琐,但只要你熟悉它的脾气,掌握好离合和油门的配合,它能带你去任何地方,而且路上绝不抛锚。下次再遇到数据库迁移,别慌,先深呼吸,按照我说的步骤,盘点、选参、备库、导入、校验,一步一步来。这过程虽然不炫酷,但稳如老狗。毕竟,咱们这行,稳,比什么都重要。


