阿里云rds搭建MySQL主从复制的问题

阿里云rds搭建MySQL主从复制的问题

01Rowsizetoolarge问题

关于阿里云的MySQL rds云实例上搭建ECS的主从复制问题,之前5月13号的文章中讲过,今天在搭建的时候出现了另外一个问题,我们这里分析一下。

我们知道,搭建MySQL主从复制的步骤如下:

1、主库进行数据备份,带上master-data参数

2、主库分配复制用户的账号密码,以供从库进行复制

3、从库应用主库的备份,并使用偏移量或者GTID的方式进行复制

今天在使用阿里云ECS搭建线上MySQL rds实例主从复制的时候,在主库上进行了数据备份,当在从库上面应用主库的备份表的时候,遇到了一个错误,如下:

ERROR1118(42000):Rowsizetoolarge(8126).
ChangingsomecolumnstoTEXTorBLOBmayhelp.Incurrentrowformat,BLOBprefixof0bytesisstoredinline.

QueryOK,0rowsaffected(0.00sec)

ERROR1146(42S02):Table'tbl75.t_family_history'doesn'texist
ERROR1146(42S02):Table'tbl75.t_family_history'doesn'texist
ERROR1146(42S02):Table'tbl75.t_family_history'doesn'texist
看这个提示,应该是行溢出的问题,这里交代一下主从库的环境:

主库 官方MySQL5.7.26版本
从库 Percona Server5.7.18版本

因为之前有过这样复制成功的案例,首先排除版本差异引起的问题,主库上既然能通过,从库上不能通过,那么一定是出现了某些参数不一致导致的,现在的问题就是定位到底是哪个参数导致的问题了。查了查google和Stack Overflow,上面给出的解释有以下几种:

第一种,修改相关参数
但是实际上我的ECS参数已经设置成了下图中的样子,所以这种方法不奏效。

第二种,修改存储引擎为MyISAM
这个显然是不可取的,因为线上的游戏表存储引擎是innodb,改了就坏了。

第三种,修改参数
max_allowed_packet=1G,这个参数代表以字节发送给服务器的最大数据包大小
innodb_log_file_size = 256M mysql事务日志文件(ib_logfile0)的大小 。
innodb_log_buffer_size = 512M 该参数确保脏数据在被写入到日志文件之前有足够大的日志缓冲区来保存。

也就是把这3个参数往大的改,使得log file和最大通信包的大小变大,这3个参数都进行了尝试,没有解决这个问题。

第四种,修改数据页的大小参数。、
innodb_page_size=32K 这种也是不可取的,数据页的大小参数一旦修改,那么会影响到数据预热和数据落盘,改变了内存和磁盘之间交互的最小单元,很有可能引发一些不确定的问题,这个参数是比较暴力的做法,不建议修改。

第五种,修改InnoDB严格检查模式。开启此功能后,当创建表(CREATE TABLE)、更改表(ALTER TABLE)和创建索引(CREATE INDEX)语句时,如果写法有错误,不会有警告信息,而是直接抛出错误。

对比了一下线上rds和ECS上的参数,发现阿里云的线上rds上关闭了这个参数,而ECS上是打开的,所以修改了ECS上的该参数,重启数据库,发现问题解决。

02复制过程中的ha_health_check问题 这个问题在之前的文章中讲过,线上环境的rds上的mysql系统库中包含表ha_health_check表,这个表的主要作用是做心跳检测,但是本地的ECS上的mysql系统库中没有表ha_health_check,之前的解决方法是直接在本地创建这个表,线上的rds中这个表包含了3条数据,我们只需要将这三条数据进行拷贝到本地ECS上即可。

今天在实践的过程中,发现拷贝完这三条记录,主库上的这三条记录一直会发生变化,等到在从库上更新之后,主库上已经不是刚才的值了,也就是说主从库的数据不一致。所以开启复制之后,从库一直报错,报错的内容是要更新的相关记录不存在。

解决这个问题,现在看来有2种方法;
一种是设置从库的slave_exec_mode参数为idempotent,而不是strict,也就是设置从库执行模式为幂等,非严格模式,这样在从库上发现要更新的记录不存在时,会自动跳过这个update语句,但是这样该有一个问题,就是针对真实的表,也会产生数据不一致的问题。这显然是不符合标准的。

另外一种方法是直接在复制的时候,忽略这个表,也就是写清楚参数Replicate_Wild_Ignore_Table,也就是在实例的my.cnf文件中配置一些规则去规避mysql系统库下面的表同步,当然,其他的系统库,类似sys和information_schema也可以进行配置,配置方法如下:
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=information_schema.%
replicate-wild-ignore-table=performance_schema.%
replicate-wild-ignore-table=sys.%
这样,在复制的时候,就不会检查这个参数了。