RDS for Mysql 迁移至本地数据库并建立主从
工具
- Xtrabackup (下载地址:https://www.percona.com/downloads/XtraBackup/LATEST)
- centos7
- mysql5.6+
1. 安装Xtrabackup工具
yum install percona-xtrabackup-22
也可以用上面给出的下载地址下载 source code,自行编译安装。
2. 下载RDS备份数据
打开阿里云控制台,下载 RDS 的物理备份文件,若没有备份文件,可以点击右上角的备份实例,添加临时备份任务。复制备份文件的链接后,下载到本地服务器:
wget -c 'https://rdsbak-shanghai.oss-cn-shanghai.aliyuncs.com/exampleurl' -O /opt/filename.tar.gz
注意,这里的备份数据链接必须用单引号包起来,是因为链接中带有参数,避免被编译。否则会报403错误
3. 解压备份数据
tar vizxf filename.tar.gz -C /opt/filename
这里的 filename.tar.gz 为刚刚下载的备份文件。
4. 恢复数据文件
cd filename
ll
显示如下,其中 newcontest、mysql 和 test 为云数据库中存在的数据库。
-rw-rw---- 1 root root 450 2月 27 13:58 backup-my.cnf
-rw-rw---- 1 root root 209715200 2月 27 16:57 ibdata1
-rw-r--r-- 1 root root 1048576000 2月 27 16:57 ib_logfile0
-rw-r--r-- 1 root root 1048576000 2月 27 16:57 ib_logfile1
-rw-rw---- 1 root root 27894872 2月 27 13:57 log000000000002.tokulog27
drwxr-xr-x 2 root root 4096 2月 27 16:56 mysql
drwxr-xr-x 2 root root 8192 2月 27 16:56 newcontest
drwxr-xr-x 2 root root 4096 2月 27 16:56 performance_schema
drwxr-xr-x 2 root root 19 2月 27 16:56 test
-rw-rw---- 1 root root 16384 12月 6 10:37 tokudb.directory
-rw-rw---- 1 root root 16384 12月 6 10:37 tokudb.environment
-rw-rw---- 1 root root 16384 12月 6 10:37 tokudb.rollback
-rw-rw---- 1 root root 71 2月 27 13:58 xtrabackup_binlog_info
-rw-r--r-- 1 root root 24 2月 27 16:57 xtrabackup_binlog_pos_innodb
-rw-rw---- 1 root root 95 2月 27 16:57 xtrabackup_checkpoints
-rw-rw---- 1 root root 661 2月 27 13:58 xtrabackup_info
-rw-rw---- 1 root root 2097152 2月 27 16:57 xtrabackup_logfile
-rw-rw---- 1 root root 76 2月 27 13:58 xtrabackup_slave_filename_info
-rw-rw---- 1 root root 113 2月 27 13:58 xtrabackup_slave_info
执行:
innobackupex --defaults-file=./backup-my.cnf --apply-log ./
系统显示 innobackupex: completed OK!
,则数据恢复成功。
5. 修改配置文件
vim backup-my.cnf
将backup-my.cnf
中的 innodb_fast_checksum
、innodb_page_size
、innodb_log_block_size
注释掉,并且添加 datadir=/usr/local/mysql/data
,如下所示。
# This MySQL options file was generated by innobackupex.
# The MySQL server
[mysqld]
innodb_checksum_algorithm=innodb
innodb_log_checksum_algorithm=innodb
innodb_data_file_path=ibdata1:200M:autoextend
innodb_log_files_in_group=2
innodb_log_file_size=1048576000
#innodb_fast_checksum=false
#innodb_page_size=16384
#innodb_log_block_size=512
innodb_undo_directory=.
innodb_undo_tablespaces=0
datadir=/usr/local/mysql/data
rds_encrypt_data=false
innodb_encrypt_algorithm=aes_128_ecb
6. 将数据文件拷贝到mysql的data文件夹
这里以/opt/mysql/data
-> /usr/local/mysql/data
为例
//停止mysql服务
systemctl stop mysqld.service
//查看是否存在mysql进程
ps -ef|grep mysqld
//清除对应进程
kill -9 进程号
//拷贝文件
\cp -rf /opt/mysql/data/* /usr/local/mysql/data
7. 修改文件属主
chown -R mysql:mysql /usr/local/mysql/data
8. 重启mysq服务
systemctl restart mysqld.service
验证数据是否已经更新
9. 设置本地从服务器
本地 mysql 的版本至少在5.6.16及以上,需要在 mysql 的配置文件(/usr/local/mysql/etc/my.cnf
)中添加一些参数
server-id ###Slave配置需要
master-info-repository=file### Slave配置需要
relay-log-info_repository=file### Slave配置需要
binlog-format=ROW### Slave配置需要
gtid-mode=on###开启GTID需要
enforce-gtid-consistency=true###开启GTID需要
innodb_data_file_path=ibdata1:200M:autoextend###使用RDS的物理备份中的backup-my.cnf参数
innodb_log_files_in_group=2###使用RDS的物理备份中的backup-my.cnf参数
innodb_log_file_size=1048576000###使用RDS的物理备份中的backup-my.cnf参数
10. 清理同步关系
####用于重置本地MySQL的复制关系
mysql> reset slave;
####这一步操作有可能报错:
ERROR 1794 (HY000): Slave is not configured or failed to initialize properly. You must at least set –server-id to enable either a master or a slave. Additional error messages can be found in the MySQL error log.
原因是由于 RDS 的备份文件中包含了 RDS 的主从复制关系,需要把这些主从复制关系清理掉,清理方法:
use mysql;
truncate table slave_relay_log_info;
truncate table mysql.slave_master_info;
truncate table mysql.slave_worker_info;
11. 设置gtid
gtid 信息存在/usr/local/mysql/data/xtrabackup_slave_info
文件中
执行:
set global gtid_purged='fddb0cbe-bb5c-11e6-989f-288023a1a6d4:1-1311995';
这一步有可能报错:)
ERROR 1840 (HY000): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.
执行:
reset master;
set global gtid_purged='fddb0cbe-bb5c-11e6-989f-288023a1a6d4:1-1311995';
12. 设置slave
change master to master_host = 'rdsExampleUrl.mysql.rds.aliyuncs.com', master_port = 3306, master_user = 'username', master_password='password', master_auto_position = 1;
启动 slave:
start slave;
##检测slave运行状态
show slave status\G;
当 Slave_IO 和 Slave_SQL 均为 YES 时,表示成功:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
13. 后记
在设置 slave 时经常会遇到1236(不是12306!)错误:
Last_IO_Errno: 1236
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.'
从报错信息上显示为:主库清理(purge)掉了从库还没有接受的事物。
先普及一下 GTID 的概念:GTID 即全局事务 ID(global transaction identifier),GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的唯一标识。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增,所以GTID能够保证每个MySQL实例事务的执行(不会重复执行同一个事务,并且会补全没有执行的事务)。下面是一个GTID的具体形式:
4e659069-3cd8-11e5-9a49-001c4270714e:1-77
总结:从库在开始同步前,主库会依靠 GTID 来确认从库在开始同步以后, 能够把每一个主库上执行过的事务(包括 slave 的 SQL Thread)都复现一次,最终保持和主库完全一致。
判断的方法也很简单,基本基于两个条件:
- 主库不能清理(purge)从库还没有执行(execute)的事务(即从库的 executed_GTID 要大于主库的 GTID_Purged);
- 主库上的事务号不能低于从库(即从库的 executed_GTID 的最后一个事务要在主库的 executed_GTID 的范围之内);
我们都知道当重启 mysql 或是 binlog 文件大小达到了参数 max_binlog_size 的限制,即会清理掉(purge)过期的日志,所以当我们在 RDS 上下载前几天的备份文件到从库并设置同步的时候就得注意了:
- 主库在这段时间是否有过重启
- 主库这几天的流量是否过大。
一旦主库的 binlog 被 purged,便会出现从库的 executed_GTID 小于主库的 GTID_Purged,导致同步失败。
解决方法:通常是备份数据太过久远,所以重新在RDS上下载一份最近的数据文件,重新配置。另外出于安全性考虑,建议 RDS 上的数据每天备份一次(可设置自动备份)。