+86 13541016684Mon. - Fri. 10:00-22:00

AWS RDS Mysql数据库做主库与外部Mysql从库进行复制

AWS RDS Mysql数据库做主库与外部Mysql从库进行复制

AWS RDS Mysql数据库做主库与外部Mysql从库进行复制

最近在帮一用户迁移mysql,用户使用复制功能可以将数据从AWS RDS  MySQL 5.6 数据库实例导出到在外部运行的 MySQL 实例,在该过程中RDS Mysql实例将作为主库与外部的Mysql从库建立复制关系。外部的 MySQL可在数据中心内本地运行,也可在 Amazon EC2 实例上运行。RDS MySQL 数据库实例必须运行 5.6.13 版或更高版本。本文将介绍如何建立这种复制关系的步骤,并且指出可能由RDS实例本身特性而容易导致的一些错误,对于准备使用aws rds但又不知道如何选择配置来说,下边提供一些常用的配置方便大家做参考。

Amazon RDS价格一览

本文尝试通过一些直观的数据和表格,来看看Amazon某个规格的RDS实例到底是什么价格以及如何计费。

亚马逊RDS计费分为两个主要的部分,一个是“实例费用”(CPU和内存),另一个是“存储费用”(磁盘容量和IOPS)。这两类资源的费用,又细 分为单可用区和多可用区,另外,还可以选择“按小时计费”、又或者是“包年计费”的方式购买,这些对价格都有很大影响。本文分多个部分细致介绍了亚马逊如 何计算一个RDS实例的价格。

“实例费用”

“基本规格”

基本规格根据CPU和内存使用来划分,Amazon RDS有如下基本规格:

Snip20150319_9

 

根据实际的应用场景,选择你需要的规格。

“按小时付费”与“包年付费”

对于上面这些基本规格,你可以“按小时付费”付费,还可以选择“包年付费”。包年的方式,非常便宜,基本上只有前者的一半的价格。

“单可用区”与“多可用区”

可以简单的理解为,实例是否有一个备库。如果是单可用区,那么实例没有备库,实例故障时,用户只能从备份中恢复数据,如果实例很大,恢复的时间可能 会很长;如果是多可用区,则Amazon会为你构建一个同步备库,主实例发生故障时,Amazon会自动为你切换到备库上。多可用区实例的备份是发生在备 库上,不会影响主库的实例;而单可用区实例在备份的时候,IO则可能会又很大的影响。

当然多可用区价格也更贵,多可用区的价格则恰好是单可用区的两倍,下面是一个参考价格列表:

Snip20150319_14

 

“存储费用”

确定好了实例,接下来要做的是选择存储。存储有三个选项:“通用存储/SSD”、“预留IOPS的存储/SSD”、“传统磁盘”。另外,对于单可用区和多可用区存储的价格也是不一样的。

通用存储/SSD

“通用存储/SSD”:只会按照存储空间的大小来计费,范围是5GB到3TB,价格比较便宜。这类存储,不会按照IOPS计费,存储到底提供多少IOPS,Amazon也没有明确说明。

预留IOPS的存储/SSD

“预留IOPS的存储/SSD”:这类则是明确定义IOPS能力的存储,容量范围是100GB到3TB,IOPS能力从1000到30000,你可以根据自由选择。这类存储的计费分两项来独立计费,容量按照每GB计费;IOPS按照每一个IOPS多少钱来计费。

传统磁盘

“传统磁盘”:存储容量的价格相对便宜,但是IOPS却更贵。适合IOPS低,但是空间容量要求大的应用。

存储费用对比

详细费用列表可以参考价格列表页面,但是这个页面中的数据并不直观。下面我们来看一个具体的场景,如果购买一个多可用区的150GB的SSD磁盘,同时购买1000IOPS,存储对应的价格会是什么水平:

Snip20150319_18

 

这样就清晰了一些。

总览

有了实例价格和存储价格,那么就可以计算一个完整的RDS实例价格了,比如,我们这里计算一个使用2颗vCPU,15GB内存,150GB存储空 间,1000IOPS的实例,因为是打算用于生产环境,所以这里选择的是多可用区,并计划使用一年,那我们看看这样的实例一个月多少钱呢?

Snip20150319_20

 

有了上面这些计算和表格,我们对亚马逊RDS的价格就有了一个比较直观、清晰的认识了。

账单

下面是一个按小时实例的参考账单,刚刚建立实例不久:

Snip20150319_24

本文部分名词对照表

 

Snip20150319_22

 

AWS RDS Mysql数据库作为主从复制(Master-Slave)中的主库(Master)

在AWS RDS的文档中并没有刻意提到RDS Mysql可以作为主库与外部Mysql数据库建立长期稳定的复制关系,而只是在文档中“使用复制功能导出 Amazon RDS MySQL 5.6 数据”这部分提到了可以利用这种复制关系来将RDS中的数据导出到外部数据库。网上能找到一篇具体操作的文章,见参考资料,文章教大家Step by Step建立这种复制关系。但是由于AWS RDS本身的一些特性(限制),按文章中的方法操作可能会出现一些其他问题。

总之,在日常的数据库结构中,将AWS RDS Mysql作为主从复制中主库,将外部Mysql数据库作为从库的方法并不是Amazon官方文档中明确推荐的。请谨慎组建这样的复制关系,因为你并不能有权限来完全操作RDS Mysql实例的管理。

在下文中会将如何建立这种复制关系的步骤做具体描述,供大家参考。并且指出一些可能由RDS实例本身特性而出现的错误。

 

详细步骤

1 创建RDS Mysql 数据库实例

在AWS文档(中文英文)中以图文并茂的形式详细描述了如何创建一个RDS Mysql实例,在本文中不再重复。

本文中选择的数据库版本为5.6.21,数据库名称为awsgood, 用户名为awsgood, 密码为awsgood.com。

在RDS实例启动完成后,可以用Mysql客户端命令连接其终端节点(endpoint)并登录:

$ mysql -hawsgood.cmscpiuewome.rds.cn-north-1.amazonaws.com.cn -uawsgood -pawsgood.com

Server version: 5.6.21-log MySQL Community Server (GPL)
Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the current input statement.
mysql>

其中awsgood.cmscpiuewome.rds.cn-north-1.amazonaws.com.cn为数据库实例的终端节点,命名方式是数据库实例名+与AWS账户相关的随机字符串+rds+区域endpoint端点名。

 

2 创建外部Mysql数据库

外部Mysql数据库可以在任何位置的Linux系统中启动。本文选择将外部非RDS数据库创建在AWS EC2上,操作系统使用默认的Amazon Linux。Amazon Linux可以利用yum repository来下载和管理软件的依赖关系。

利用yum info命令查看可用的mysql版本:

$ yum info mysql
Loaded plugins: priorities, update-motd, upgrade-helper
4 packages excluded due to repository priority protections
Available Packages
Name        : mysql
Arch        : noarch
Version     : 5.5
Release     : 1.6.amzn1
Size        : 2.7 k
Repo        : amzn-main/latest
Summary     : MySQL meta package
URL         : http://www.mysql.com
License     : GPLv2 with exceptions
Description : MySQL is a multi-user, multi-threaded SQL database server. MySQL is a
: client/server implementation consisting of a server daemon (mysqld)
: and many different client programs and libraries. The base package
: contains the standard MySQL client programs and generic MySQL files.

由上可知Amazon的yum repository中最新的版本为Mysql 5.5,而我们需要用等于或者高于5.6.21 (RDS Mysql版本)的Mysql,才能作为其从库(Slave)。

在Mysql官方文档中介绍了如何利用MySQL Yum repository来安装最新GA版本Mysql的方法(文章写作时最新的GA版本是MySQL 5.6)。

$ sudo yum localinstall http://repo.mysql.com/mysql-community-release-el6-5.noarch.rpm

利用yum repolist enable命令检查MySQL yum repository被成功地添加进来。

$ yum repolist enabled | grep “mysql.*-community.*”
!mysql-connectors-community/x86_64       MySQL Connectors Community         8+4
!mysql-tools-community/x86_64            MySQL Tools Community               18
!mysql56-community/x86_64                MySQL 5.6 Community Server          95

添加了MySQL yum repository后,利用下面的命令安装Mysql 5.6版本。

$ sudo yum install mysql mysql-server
$ sudo chgrp -R mysql /var/lib/mysql
$ sudo chmod -R 770 /var/lib/mysql
$ sudo service mysqld start
$ sudo mysqladmin -u root password mypass

查看Mysql的版本:

$ mysql –version
mysql  Ver 14.14 Distrib 5.6.21, for Linux (x86_64) using  EditLine wrapper

EC2上安装的Mysql与RDS Mysql的版本相同,可以形成一个Master-Slave关系。

 

3 在RDS Mysql实例上将其配置为主库(Master)

3.1 确认RDS上的binlog已经被打开

mysql> show variables like ‘log_bin’;
+—————+——-+
| Variable_name | Value |
+—————+——-+
| log_bin       | ON    |
+—————+——-+
1 row in set (0.00 sec)

mysql> show master status;
+—————————-+———-+————–+——————+——————-+
| File                       | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+—————————-+———-+————–+——————+——————-+
| mysql-bin-changelog.015493 |      120 |              |                  |                   |
+—————————-+———-+————–+——————+——————-+
1 row in set (0.00 sec)

3.2 创建并授权可以来读取日志文件的用户

 mysql> CREATE USER ‘repluser’@’%’ IDENTIFIED BY ‘replpass’;
Query OK, 0 rows affected (0.17 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO ‘repluser’@’%’;
Query OK, 0 rows affected (0.01 sec)

3.3 利用上一步创建和授权的账号,用mysqlbinlog来测试查看binlog,如下可以成功:

$ mysqlbinlog -h awsgood.cmscpiuewome.rds.cn-north-1.amazonaws.com.cn -u repluser -preplpass –read-from-remote-server -t mysql-bin-changelog.015493
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
……
CREATE USER ‘repluser’@’%’ IDENTIFIED BY PASSWORD ‘*D98280F03D0F78162EBDBB9C883FC01395DEA2BF’
/*!*/;
# at 280
#141123 16:00:43 server id 1056411688  end_log_pos 407  Query   thread_id=1333  exec_time=0     error_code=0
SET TIMESTAMP=1416758443/*!*/;
GRANT REPLICATION SLAVE ON *.* TO ‘repluser’@’%’
/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

在此处可能会出现如下错误:

Got fatal error 1236 from master when reading data from binary log: ‘Could not find first log file name in binary log index file’

如果出现,则需要利用show master status命令查看最新的binlog文件,有可能已经切换成mysql-bin-changelog.015494。再利用mysqlbinlog命令重新执行,-t参数后面跟上最新的binlog文件。

关于这个错误,是由RDS本身的机制导致的,具体原因和较好的解决方法请参看后文中的“RDS Mysql特性及常见问题”部分。

 

4 将EC2上的Mysql数据库配置为从库(Slave)

4.1 在配置文件/etc/my.cnf的[mysqld]下面加入以下几行:

[mysqld] log-bin=mysql-bin
server_id=2   # server-id 可以选在为 1 到(2的32次方–1)之间的整数
relay_log=mysql-relay-bin
log_slave_updates=1
read_only=1
replicate-ignore-db=mysql

4.2 重启mysql服务

$ sudo service mysqld restart

4.3 在Slave数据库上指定并连接Master

在RDS主库上利用show master status来查看最新的binlog文件和位置,例如分别为mysql-bin-changelog.015496和120。

则在Slave数据库上用如下命令连接RDS Master:

mysql>CHANGE MASTER TO

-> MASTER_HOST=’awsgood.cmscpiuewome.rds.cn-north-1.amazonaws.com.cn’,
-> MASTER_USER=’repluser’,
-> MASTER_PASSWORD=’replpass’,
-> MASTER_LOG_FILE=’mysql-bin-changelog.015496′,
-> MASTER_LOG_POS=120;

4.4 开始复制

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

4.5 查看slave的复制状态

mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: test1.cmscpiuewome.rds.cn-north-1.amazonaws.com.cn
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin-changelog.015496
Read_Master_Log_Pos: 120
Relay_Log_File: mysql-relay-bin.000004
Relay_Log_Pos: 566
Relay_Master_Log_File: mysql-bin-changelog.015496
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 410
Relay_Log_Space: 775
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1056411688
1 row in set (0.00 sec)

 

5 测试同步

在RDS Master Mysql上

mysql> create database testdb;
Query OK, 1 row affected (0.06 sec)

mysql> use testdb
Database changed
mysql> create table test (id int, string varchar(100));
Query OK, 0 rows affected (0.24 sec)

在EC2 Mysql上查看testdb和test table是否都已经同步过来

mysql> use testdb
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+——————+
| Tables_in_testdb |
+——————+
| test             |
+——————+
1 row in set (0.00 sec)

mysql> show create table test\G
*************************** 1. row ***************************
Table: test
Create Table: CREATE TABLE `test` (
`id` int(11) DEFAULT NULL,
`string` varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

由上面的测试结果可知,在Master上建立的数据库和表成功已经同步到Slave上。

 

RDS Mysql特性及常见问题

1 binglog特性

如果按照上文的步骤执行,很有可能会遇到的一个问题就是:

Got fatal error 1236 from master when reading data from binary log: ‘Could not find first log file name in binary log index file’

因为RDS Mysql设计的理念就是过几分钟就将binlog切换(rorate),而不是等到到达最大size时才做切换。并且在完成切换后,会将旧的 binlog文件即时上传到Amazon S3中进行存储,并将实例上的binlog文件清除。所以在外部的Slave来指定RDS Master的binlog文件和位置时,可能很容易发生无法找到文件的报错。

RDS提供了存储过程mysql.rds_set_configuration给用户,功能是修改binlog文件在RDS实例中的保留时间,以小时为单位,在AWS RDS文档中进行了说明。

下例将保留期设置为 1 天,并查看修改结果:

mysql> call mysql.rds_set_configuration(‘binlog retention hours’, 24);
Query OK, 0 rows affected (0.00 sec)

mysql> call mysql.rds_show_configuration\G
*************************** 1. row ***************************
name: binlog retention hours
value: 24
description: binlog retention hours specifies the duration in hours before binary logs are automatically deleted.
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

利用修改RDS的保留时间,可以很大程度上避免找不到binlog的报错。

 

2 mysql数据库

在上面的详细步骤中,配置从库my.cnf时加上了语句replicate-ignore-db=mysql,表示在复制时不复制数据库mysql 中的内容。这样配置的目的是因为RDS Mysql数据库中存在一些RDS特有的表,这些表在普通的Mysql数据库中可能不存在,如果直接将RDS Mysql中的mysql库与外部Mysql的mysql库复制,可能会导致如下报错:

Last_SQL_Error: Error ‘Table ‘mysql.rds_heartbeat2′ doesn’t exist’ on query. Default database: ”. Query: ‘INSERT INTO mysql.rds_heartbeat2(id, value) values (1,1416392460255) ON DUPLICATE KEY UPDATE value = 1416392460255′

从上面的报错可知,外部的Mysql数据库并没有rds_heartbeat2表,从而导致复制关系失败。

 

参考资料

http://www.ruempler.eu/2013/07/07/replicating-aws-rds-mysql-databases-to-external-slaves/