摘要
阿里云官网表示目前不支持RDS For MySQL 5.7 到自建MySQL的主从搭建,本篇文档尝试突破阿里云限制。经过多次验证发现,PerconaServer与RDS的兼容性最高, 破解方法为:使用Percona Server,在物理备份还原后,手动修改系统库引擎,已达到数据实时同步,且能够正常于从库进行权限配置。
背景
写在前面
目前很多客户在阿里云上使用的MySQL数据库版本多数为RDS For MySQL 5.7,尽管RDS本身拥有很高的数据库可用性和服务可用性,但都是基于阿里云本身,客户希望在保证阿里云上数据库高可用的同时,在本地也有一份保障,因此云上RDS到IDC的数据库实时同步成为一个重要的需求场景。
目前阿里云只提供DTS工具来实现云上到IDC机房数据实时同步的场景,一个最小规格的同步链路其费用为27840元/年,接近3万元。
为何只能通过DTS同步工具来实现从RDS到自建数据库的同步关系呢?
我们看看阿里官方的解释:
RDS 目前已经不支持 MYISAM 引擎了,所有的数据库,包括系统库默认都是使用InnoDB存储引擎。所以如果是通过自建的replication 同步就会有不兼容的问题,例如从库无法管理用户,甚至无法正常启动等无法预知的问题。
如果需求是从RDS到自建数据库的同步关系,建议您使用DTS 做业务数据的同步。
DTS工具的痛点
- 使用DTS做云上到自建数据库业务数据的同步时,只能选择DTS迁移工具,而该工具在使用时必须保证没有DDL操作,否则就会停止同步,相信没有哪个业务能够长期保证不执行DDL操作,因此DTS迁移工具不能一直使用。只能是周期性地去同步RDS和自建MySQL的数据,属于非实时同步,且每次都是全量同步,同步耗时是需要根据数据量的情况来评估的(1T的数据预计在10小时)。
 - DTS同步工具,虽然可以支持同步过程中执行DDL操作,但是目前只支持从RDS到RDS For MySQL,且同步过程中不支持触发器。
 - 如果能够利用MySQL自带的Replication技术去实现数据同步,一来可以完全实现实时同步,而来还能够节省支出。
 
探索解决方法
阿里云RDS For MySQL 5.7 的版本号并不是唯一的,有5.7.17、5.7.20 等,大版本号确定为5.7,小版本号不确定。

自建MySQL选择以下本版进行尝试:
- MySQL 5.7.20
 - Percona Server 5.7.20
 
初步探索
RDS For MySQL 5.7 到自建MySQL 5.7.20/Percona Server5.7.20 搭建主从同步架构:
- 配置从库不同步RDS主库的系统表
 
# skip rep  | 
- 非系统库数据同步正常
 - 从库无法执行grant命令,即无法添加授权信息
 - 从库无法对系统表mysql.user表执行insert操作
 - 从库无法对系统表mysql.user表执行updat操作
 
报错如下:
ERROR 1064 (42000): Unknown trigger has an error in its body: 'Unknown system variable 'maintain_user_list''  | 
问题根源
通过初步对比系统库mysql,可以发现一些端倪:
- 和MySQL官方的社区版相比,Percona的版本与RDS兼容性更高
 - RDS与Percona版本在系统库引擎的差异如下图所示:
 
select table_name,engine from information_schema.tables where table_schema='mysql';  | 

破解方法
经过多次验证发现,RDS使用的应该是Percona的数据库服务器,并进行了二次开发,破解的方法为物理备份还原后,手动修改系统库。
破解环境概览
| 数据库环境 | 说明 | 
|---|---|
| 阿里云RDS | 5.7.20 | 
| 自建MySQL服务器系统 | CentOS 7.4 | 
| 自建MYSQL数据库版本 | Percona Server 5.7.20 | 
具体操作步骤
1 自建MySQL安装
wget "https://raw.githubusercontent.com/BoobooWei/DBA_Mysql/master/scripts/auto_intall/install_perconaxerver5.7.20_centos7.sh"  | 
如果返回5.7.20-log则说明已成功安装并启动了数据库服务。
软件架构如下:
| 自建数据库软件架构 | 说明 | 
|---|---|
| 安装目录 | /alidata/mysql | 
| 数据目录 | /alidata/mysql/data | 
| 守护进程 | /alidata/mysql/bin/mysqld | 
| 监听端口 | 3306 | 
| 配置文件 | /etc/my.cnf | 
| RDS备份文件下载解压目录 | /alidata/mysql/xtrabackup_data | 
2 全备份文件下载并解压
登陆到阿里云RDS控制台,选择最近的全备份进行下载,全备份时间不能超过binlog设置的过期时间。
curl -o "hins4764419_data_20180913072637.tar.gz" "http://rdsbak-shanghai-v2.oss-cn-shanghai-internal.aliyuncs.com/asldkjalsdkjflasdjf"  | 
下载pxc工具以及阿里云专用解压工具
wget https://raw.githubusercontent.com/BoobooWei/DBA_Mysql/master/scripts/auto_intall/install_rds_pxc_centos7.sh  | 
开始解压全备份数据
全备份恢复  | 
如果数据量很大,这一步会非常耗时。
3 将全备份数据恢复
停止数据库服务
/alidata/mysql/support-files/mysql.server stop  | 
将初始化的数据库数据目录重命名为data_back
mv /alidata/mysql/data/ /alidata/mysql/data_back  | 
将pxc恢复的全备份文件目录重命名为data
mv /alidata/mysql/xtrabackup_data /alidata/mysql/data  | 
启动本地数据库
/alidata/mysql/support-files/mysql.server start  | 
4 手动修改系统库
备份RDS的元数据(与本地有差别的表)
mysqldump -u$rds_user -p$rds_pwd -h$rds_url -P $rds_port mysql columns_priv db event func ndb_binlog_index proc procs_priv proxies_priv tables_priv user --set-gtid-purged=OFF --opt --default-character-set=utf8 --single-transaction --hex-blob --skip-triggers --max_allowed_packet=824288000 -d > mysql.sys.meta.sql  | 
备份rds差异表的数据
mysqldump -u$rds_user -p$rds_pwd -h$rds_url -P $rds_port mysql columns_priv db event func ndb_binlog_index proc procs_priv proxies_priv tables_priv user --set-gtid-purged=OFF --opt --default-character-set=utf8 --single-transaction --hex-blob --skip-triggers --max_allowed_packet=824288000 -t > mysql.sys.data.sql  | 
删除本地恢复的差别表
cat > local_drop.sql << ENDF  | 
删除本地数据文件
cd $datadir  | 
导入元数据(即表结构)
sed -i 's/ENGINE=InnoDB/ENGINE=myisam/' mysql.sys.meta.sql  | 
导入数据
mysql mysql < mysql.sys.data.sql  | 
添加权限
cat > local_grant.sql << ENDF  | 
重新启动服务
/alidata/mysql/support-files/mysql.server restart  | 
5 配置主从
停止本地数据库的replication线程,并清空相关配置
stop slave;  | 
修改GTID参数
SET GLOBAL gtid_purged='$gtid';  | 
配置主库同步信息
change master to master_host='$url',master_user='$user',master_password='$pwd',master_auto_position=1;  | 
启动replication
start slave;  | 
查看主从明细
show slave status\G;  | 
总结
下面这幅图中最左侧为PerconaServer的系统表清空,中间这副是将RDS系统表修改后的结果,最右边是RDS的系统表情况。

通过手动修改自建MySQL系统库mysql中的表引擎,我们达到了RDS到自建MySQL实时同步的目的,且经过生产环境验证,该方法完全可以突破阿里限制实现云上和IDC机房的数据实时同步。