MySQL 逻辑备份工具最常用的就是 mysqldump 了,一般我们都是备份整个实例或部分业务库恢复场景可能就比较多了,比如恢复某个库或某个表等,那么如何从全备中恢复单库或单表,这其中又有哪些隐藏的坑呢?
如何恢复单库或单表
每个数据库实例中都不止一个库,一般备份都是备份整个实例,但恢复需求又是多种多样的,比如说我想只恢复某个库或某张表,这个时候应该怎么操作呢?
如果你的实例数据量不大,可以在另外一个环境恢复出整个实例,然后再单独备份出所需库或表用来恢复。不过这种方法不够灵活,并且只适用数据量比较少的情况。
其实从全备中恢复单库还是比较方便的,有个 --one-database
参数可以指定单库恢复,下面来具体演示下:
1 | # 查看及备份所有库 |
除了上述方法外,恢复单库或单表还可以采用手动筛选的方法。这个时候 Linux 下大名鼎鼎的 sed
和 grep
命令就派上用场了,我们可以利用这两个命令从全备中筛选出单库或单表的语句,筛选方法如下:
1 | # 从全备中恢复单库 |
小心有坑
对于上述手动筛选来恢复单库或单表的方法,看起来简单方便,其实隐藏着一个小坑,下面我们来具体演示下:
1 | # 备份整个实例 |
如果你仔细观察的话,会发现恢复出来的数据有问题,貌似时间不太对,你再仔细看看,是不是有的时间差了8小时!详细探究下来,我们发现 timestamp 类型字段的时间数据恢复有问题,准确来讲备份文件中记录的是0时区,而我们系统一般采用东八区,所以才会出现误差8小时的问题。
那么你会问了,为什么全部恢复不会出问题呢?问的好,我们看下备份文件就知道了。
1 | # 备份文件开头 |
仔细看备份文件,你会发现 mysqldump 备份出来的文件中,首先会将会话时区改为0,结尾处再改回原时区。这就代表着,备份文件中记录的时间戳数据都是以0时区为基础的。如果直接执行筛选出的SQL,就会造成0时区的时间戳插入的东八区的系统中,显然会造成时间相差8小时的问题。
看到这里,不知道你是否看懂了呢,可能有过备份恢复经验的同学好理解些。解决上述问题的方法也很简单,那就是在执行SQL文件前,更改当前会话时区为0,再次来演示下:
1 | # 清空test_db表数据 |
总结:
我们在网络中很容易搜索出恢复单库或单表的方法,大多都有提到上述利用 sed 、grep 命令来手动筛选的方法。但大部分文章都未提及可能出现的问题,如果你的表字段有timestamp 类型,用这种方法要格外注意。无论面对哪种恢复需求,我们都要格外小心,不要造成越恢复越糟糕的情况,最好有个空实例演练下,然后再进行恢复。