记一次从阿里云rds备份单库到服务器
问题产生
在线上主从同步的slave数据库中产生了如下的错误:
1 | ERROR 1787 (HY000): When @@GLOBAL.ENFORCE_GTID_CONSISTENCY = 1, the statements CREATE TEMPORARY TABLE and |
使用show slave status
可以查看从库当前的同步状态,发现I/O状态已经变为NO,尝试使用:
1 | set global sql_slave_skip_counter = 1; |
之后产生如下的问题:
1 | ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction |
根据错误说明使用一个空事务来跳过异常,代码如下:
1 | STOP SLAVE; |
然而这样会导致主从的数据可能产生不一致的情况,这是我们想要避免的,并且希望主库可以不锁表导出数据即可进行备份.
Xtrabackup
查看阿里云的官方文档:RDS for MySQL 物理备份文件恢复到自建数据库发现可以使用Xtrabackup来进行恢复.
操作系统中已安装数据恢复工具Percona XtraBackup。MySQL 5.6及之前的版本需要安装 Percona XtraBackup 2.3。MySQL 5.7版本需要安装 Percona XtraBackup 2.4。可以从Percona XtraBackup官网下载安装,安装指导请参见官方文档 Percona XtraBackup 2.3、Percona XtraBackup 2.4。
Xtrabackup的单表恢复
但是上面的官方文档中仍旧有一个问题,在文档中写到:
说明 由于软件限制,目前只支持将云数据库MySQL的备份文件恢复到安装在Linux系统中的自建MySQL数据库中。
而在恢复数据的时候,我们想要只对业务用到的数据库进行恢复,mysql的配置信息库不希望恢复到从库中去(由于主从用户信息等都不相同).也就是说从备份的源上无法进行库的指定(Xtrabackup支持表的指定但是阿里云RDS没有这个选项).
在查看了Xtrabackup网站上的教程之后,发现Xtrabackup可以单独对一张表进行恢复,即在阿里云文档的:
1 | # 解包 |
操作也就是解压了需要同步的数据之后:
创建新表
使用sql语句创建对应需要恢复的表(没有数据库就先创建数据库):
1 | -- 官方例子中用到的表 |
删除表空间
1 | mysql> ALTER TABLE name_p4 DISCARD TABLESPACE; |
拷贝数据
1 | 将对应的数据库的对应的表(备份数据目录下)拷贝到mysql文件夹下同数据库的同表目录下 |
导入表空间
1 | mysql> ALTER TABLE name_p4 IMPORT TABLESPACE; |
导入指定的库
知道了上面的对单表导入的原理,那么对指定的库的数据导入过程其实就是重复导入表的过程直至全部的表都恢复到库中为止.
mysqlfrm介绍
mysqlfrm 是一个恢复性质的工具,用来读取.frm文件并从该文件中找到表定义数据生成CREATE语句。在大多数情况下,生成的CREATE语句用于在另一个服务器上创建表或进行诊断等。
我们使用mysqlfrm来生成数据表创建语句.
恢复单库的脚本
1 | !/bin/bash |
注意
- 一开始由于部分表仍旧使用MyISAM引擎导致行格式不一致而使得表空间更改语句不生效,而MyISAM表也不支持compact,所以从库全部使用的InnoDB作为存储引擎.
- 如果数据库用户配置比较复杂,可以优先尝试mysql相关命令是否生效,不生效则进行调整.
启动主从同步
在启动之前,需要设置GTID相关信息(仅限于自己的生产服务器,文档中没有提到):
1 | slave1> reset master; |
然后使用CHANGE MASTER
语句来进行主从同步设置.
参见How to create/restore a slave using GTID replication in MySQL 5.6
参考连接
xtrabackup restore specific database from a full backup(单库的恢复方法)