Dashuang Du.
Dashuang Du.

study and practice, years of it.

RDS for Mysql 迁移至本地数据库并建立主从

RDS for Mysql 迁移至本地数据库并建立主从

2016, Nov 08    

工具


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_checksuminnodb_page_sizeinnodb_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 的进程)
//停止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;
然后重启 mysql 后,重新执行`reset slave`。

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)都复现一次,最终保持和主库完全一致。

判断的方法也很简单,基本基于两个条件:

  1. 主库不能清理(purge)从库还没有执行(execute)的事务(即从库的 executed_GTID 要大于主库的 GTID_Purged);
  2. 主库上的事务号不能低于从库(即从库的 executed_GTID 的最后一个事务要在主库的 executed_GTID 的范围之内);

我们都知道当重启 mysql 或是 binlog 文件大小达到了参数 max_binlog_size 的限制,即会清理掉(purge)过期的日志,所以当我们在 RDS 上下载前几天的备份文件到从库并设置同步的时候就得注意了:

  • 主库在这段时间是否有过重启
  • 主库这几天的流量是否过大。

一旦主库的 binlog 被 purged,便会出现从库的 executed_GTID 小于主库的 GTID_Purged,导致同步失败。

解决方法:通常是备份数据太过久远,所以重新在RDS上下载一份最近的数据文件,重新配置。另外出于安全性考虑,建议 RDS 上的数据每天备份一次(可设置自动备份)。