关于主从复制:MySQL主从复制原理剖析与应用实践

vivo 互联网服务器团队- Shang YongxingMySQL Replication(主从复制)是指数据变动能够从一个MySQL Server被复制到另一个或多个MySQL Server上,通过复制的性能,能够在单点服务的根底上裁减数据库的高可用性、可扩展性等。 一、背景MySQL在生产环境中被宽泛地利用,大量的利用和服务都对MySQL服务存在重要的依赖关系,能够说如果数据层的MySQL实例产生故障,在不具备牢靠降级策略的背景下就会间接引发下层业务,甚至用户应用的阻碍;同时MySQL中存储的数据也是须要尽可能地缩小失落的危险,以防止故障时呈现数据失落引发的资产损失、客诉等影响。 在这样对服务可用性和数据可靠性需要的背景下,MySQL在Server层提供了一种牢靠的基于日志的复制能力(MySQL Replication),在这一机制的作用下,能够轻易构建一个或者多个从库,进步数据库的高可用性、可扩展性,同时实现负载平衡: 实时数据变动备份主库的写入数据会继续地在冗余的从库节点上被执行保留,缩小数据失落的危险横向拓展节点,撑持读写拆散当主库自身接受压力较大时,能够将读流量扩散到其它的从库节点上,达成读扩展性和负载平衡高可用性保障当主库产生故障时,能够疾速的切到其某一个从库,并将该从库晋升为主库,因为数据都一样,所以不会影响零碎的运行具备包含但不限于以上个性的MySQL集群就能够笼罩绝大多数利用和故障场景,具备较高的可用性与数据可靠性,以后存储组提供的生产环境MySQL就是基于默认的异步主从复制的集群,向业务保障可用性99.99%,数据可靠性99.9999%的在线数据库服务。 本文将深入探讨MySQL的复制机制实现的形式, 同时探讨如何具体地利用复制的能力来晋升数据库的可用性,可靠性等。 二、复制的原理2.1 Binlog 的引入从比拟宽泛的角度来探讨复制的原理,MySQL的Server之间通过二进制日志来实现实时数据变动的传输复制,这里的二进制日志是属于MySQL服务器的日志,记录了所有对MySQL所做的更改。这种复制模式也能够依据具体数据的个性分为三种: Statement:基于语句格局Statement模式下,复制过程中向获取数据的从库发送的就是在主库上执行的SQL原句,主库会将执行的SQL原有发送到从库中。Row:基于行格局Row模式下,主库会将每次DML操作引发的数据具体行变动记录在Binlog中并复制到从库上,从库依据行的变更记录来对应地批改数据,但DDL类型的操作仍然是以Statement的格局记录。Mixed:基于混合语句和行格局MySQL 会依据执行的每一条具体的 SQL 语句来辨别看待记录的日志模式,也就是在 statement 和 row 之间抉择一种。最早的实现是基于语句格局,在3.23版本被引入MySQL,从最后起就是MySQL Server层的能力,这一点与具体应用的存储引擎没有关联;在5.1版本后开始反对基于行格局的复制;在5.1.8版本后开始反对混合格局的复制。 这三种模式各有优劣,相对来说,基于Row的行格局被利用的更宽泛,尽管这种模式下对资源的开销会偏大,但数据变动的准确性以及可靠性是要强于Statement格局的,同时这种模式下的Binlog提供了残缺的数据变更信息,能够使其利用不被局限在MySQL集群零碎内,能够被例如Binlogserver,DTS数据传输等服务利用,提供灵便的跨零碎数据传输能力, 目前互联网业务的在线MySQL集群全部都是基于Row行格局的Binlog。 2.2  Binlog 的要点2.2.1 Binlog事件类型对于Binlog的定义而言,能够认为是一个个繁多的Event组成的序列,这些独自的Event能够次要分为以下几类: 各类Event呈现是具备显著的法则的: XID_EVENT标记一个事务的结尾当产生了DDL类型的QUERY_EVENT,那么也是一次事务的完结提交点,且不会呈现XID_EVENTGTID_EVENT只有开启了GTID_MODE(MySQL版本大于5.6)TABLE_MAP_EVENT必然呈现在某个表的变更数据前,存在一对多个ROW_EVENT的状况除了下面和数据更贴近的事件类型外,还有ROTATE_EVENT(标识Binlog文件产生了切分),FORMAT_DESCRIPTION_EVENT(定义元数据格式)等。 2.2.2 Binlog的生命周期Binlog和Innodb Log(redolog)的存在形式是不同的,它并不会轮转反复覆写文件,Server会依据配置的单个Binlog文件大小配置一直地切分并产生新的Binlog,在一个.index文件记录以后硬盘上所有的binlog文件名,同时依据Binlog过期工夫回收删除掉过期的Binlog文件,这两个在目前自建数据库的配置为单个大小1G,保留7天。 所以这种机制背景下,只能在短期内追溯历史数据的状态,而不可能残缺追溯数据库的数据变动的,除非是还没有产生过日志过期回收的Server。  2.2.3 Binlog事件示例Binlog是对Server层失效的,即便没有从库正在复制主库,只有在配置中开启了log_bin,就会在对应的本地目录存储binlog文件,应用mysqlbinlog关上一个Row格局的示例binlog文件: 如上图,能够很显著地留神到三个操作,创立数据库test, 创立数据表test, 一次写入引发的行变更,可读语句(create, alter, drop, begin, commit.....)都能够认为是QUERY_EVENT,而Write_rows就属于ROW_EVENT中的一种。 在复制的过程中,就是这样的Binlog数据通过建设的连贯发送到从库,期待从库解决并利用。 2.2.4 复制基准值Binlog在产生时是严格有序的,但它自身只具备秒级的物理工夫戳,所以依赖工夫进行定位或排序是不牢靠的,同一秒可能有成千盈百的事件,同时对于复制节点而言,也须要无效牢靠的记录值来定位Binlog中的水位,MySQL Binlog反对两种模式的复制基准值,别离是传统的Binlog File:Binlog Position模式,以及5.6版本后可用的全局事务序号GTID。 FILE Position只有开启了log_bin,MySQL就会具备File Position的位点记录,这一点不受GTID影响。 File: binlog.000001Position: 381808617这个概念相对来说更直观,能够间接了解为以后处在File对应编号的Binlog文件中,同时曾经产生了共计Position bytes的数据,如例子中所示即该实例曾经产生了381808617 bytes的Binlog,这个值在对应机器间接查看文件的大小也是匹配的,所以File Postion就是文件序列与大小的对应值。 基于这种模式开启复制,须要显式地在复制关系中指定对应的File和Position: CHANGE MASTER TO MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POSITION=381808617;这个值必须要精确,因为这种模式下从库获取的数据齐全取决于无效的开启点,那么如果存在偏差,就会失落或执行反复数据导致复制中断。 GTIDMySQL 会在开启GTID_MODE=ON的状态下,为每一个事务调配惟一的全局事务ID,格局为:server_uuid:id ...

April 11, 2023 · 2 min · jiezi

关于主从复制:MySQL主从复制延迟解决方案

后面一篇,咱们学习到了MySQL多版本并发管制(MVCC)实现原理,这一篇咱们接着学习MySQL主从复制模式下的提早解决方案。 MySQL主从提早是指从库的数据同步比主库略有提早,造成数据差别。MySQL主从复制模式个别采纳以下办法升高提早: 1、优化网络环境:主从复制时,减小主从服务器之间网络提早对数据库同步的影响。能够思考优化网络之间连贯的带宽、减少从库的硬件性能等。 2、减少从库数量:减少从库数量能够减少数据同步的速度和可靠性,同时也能缩小每个从库的累赘,进步从库响应速度。 3、调整数据库相干参数:能够调整一些MySQL数据库中的相干参数,比方调整binlog格局、binlog缓冲区大小、innodb_flush_log_at_trx_commit等参数,采纳半同步模式,以放慢数据的同步速度。 4、分区数据库:将数据库分成多个区,每个从库只复制本人所须要的数据区,能够无效的缩小排队梗塞、网络传输等方面的提早问题。 综上所述,优化网络环境、减少从库数量、调整数据库相干参数、分区数据库等办法能够无效的升高MySQL主从复制模式的提早。 什么是主从提早在探讨如何解决主从提早之前,咱们先理解下什么是主从提早。 为了实现主从复制,从库须要通过 I/O 线程获取主库中 dump 线程读取的 binlog 内容并写入到本人的中继日志 relay log 中,从库的 SQL 线程再读取中继日志,重做中继日志中的日志,相当于再执行一遍 SQL,更新本人的数据库,以达到数据的一致性。 与数据同步无关的工夫点次要包含以下三个: 1、主库执行完一个事务,写入 binlog,将这个时刻记为 T1; 2、之后传给从库,将从库接管完这个 binlog 的时刻记为 T2; 3、从库执行实现这个事务,将这个时刻记为 T3。 所谓主从提早,就是同一个事务,从库执行实现的工夫与主库执行实现的工夫之差,也就是 T3 - T1。 能够在备库上执行 show slave status 命令,它的返回后果外面会显示 seconds_behind_master,用于示意以后备库提早了多少秒。seconds_behind_master 的计算方法是这样的: 1、每个事务的 binlog 外面都有一个工夫字段,用于记录主库上写入的工夫; 2、备库取出以后正在执行的事务的工夫字段的值,计算它与以后零碎工夫的差值,失去 seconds_behind_master。 在网络失常的时候,日志从主库传给从库所需的工夫是很短的,即 T2 - T1 的值是十分小的。也就是说,网络失常状况下,主从提早的次要起源是从库接管完 binlog 和执行完这个事务之间的时间差。 因为主从提早的存在,咱们可能会发现,数据刚写入主库,后果却查不到,因为可能还未同步到从库。主从提早越重大,该问题也更加显著。 主从提早的起源主库和从库在执行同一个事务的时候呈现时间差的问题,次要起因包含但不限于以下几种状况: 1、有些部署条件下,从库所在机器的性能要比主库性能差。 2、从库的压力较大,即从库接受了大量的申请。 3、执行大事务。因为主库上必须等事务执行实现才会写入 binlog,再传给备库。如果一个主库上语句执行 10 分钟,那么这个事务可能会导致从库提早 10 分钟。 4、从库的并行复制能力。 主从提早的解决方案解决主从提早次要有以下计划: 1、配合 semi-sync 半同步复制; ...

March 16, 2023 · 2 min · jiezi

关于主从复制:mysql主从复制实现方法

筹备好两台装置好了mysql的机器(装置在不同的机器上),如果是给予虚拟机复制的机器则须要批改/var/lib/mysql/auto.cnf 文件中的uuid 确保两台机器的uuid不一样备份主库的数据到备库 两库统一在主库上执行(已有数据)执行命令 mysqldump -uroot -pBamboocloud@1234 -A --master-data=2 --single-transaction -R -E --triggers --max-allowed-packet=64M >/tmp/full.sql将二进制文件导入到 /tmp/full.sql 中 关上vim /tmp/full.sql 找到正文的这一行 CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000008', MASTER_LOG_POS=3050;MASTER_LOG_FILE和MASTER_LOG_POS的值记录下来留作备份前面主从复制的时候要用到 而后将full.sql传输到备库所在的机器上 scp /tmp/full.sql root@10.88.1.184:/tmp 连贯到备库的mysql 执行下列命令:敞开二进制文件同步数据开启二进制文件 set sql_log_bin =0;source /tmp/full.sqlset sql_log_bin =1;此时数据同步实现 别离配置主备库的mysql配置文件 server_id=1 #指定MySQL的id log-bin=mysql-bin #开启二进制日志文件auto_increment_increment=2auto_increment_offset=1port=13306sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES -- sqlmode须要设置为非严格模式否则程序可能会报错 见https://www.cnblogs.com/zhoujinyi/p/8035413.htmllower_case_table_names=1default-storage-engine = INNODB# mysql 主从幂等模式slave_exec_mode=IDEMPOTENT# 跳过指定谬误slave-skip-errors=1032,1062 #疏忽谬误# 更新快的表不同步先replicate-ignore-table=bim.qrtz_scheduler_statereplicate-ignore-table=bim.tb_jgroupsping配置主从a) 在主库上创立可供复制的非凡账号 创立语句如下GRANT REPLICATION SLAVE ON *.* to 'replication'@'%' identified by 'Bamboocloud@1234';而后在从库上执行下列sql;CHANGE MASTER TO MASTER_HOST = '10.88.1.73', MASTER_USER = 'replication', MASTER_PORT =13306, MASTER_PASSWORD = 'Bamboocloud@1234', MASTER_LOG_FILE = 'mysql-bin.000008', MASTER_LOG_POS = 3050; master_host是主服务器的ipmaster_port=13306(这里没有配置,默认3306)master_user:Master 服务器受权用户,也就是 Master 后面创立的那个用户master_password:Master 服务器受权用户对应的明码master_log_file:Master binlog 文件名master_log_pos:Master binlog 文件中的 Postion 值 这个值代表从库从主库同步数据的节点(终点) ...

November 10, 2021 · 1 min · jiezi

dockercompose构建mysql主从复制集群

docker-compose构建mysql主从复制集群docker-compose构建 mysql 主从复制(读写分离)集群 MySQL master-slave replication with using Docker. 源码在github上: https://github.com/docker-box... 运行git clone https://github.com/docker-box/mysql-cluster.gitcd mysql-cluster./build.sh可以在build.sh内自定义对应参数提示: 运行前需要确保安装了docker和docker-compose,具体安装方法请参考官网 如果想手动安装, 则可以按照build.sh内的命令来手动执行即可 测试看看效果给主库创建一个表, 并添加两条数据docker exec mysql_master sh -c "export MYSQL_PWD=111; mysql -u root mydb -e 'create table code(code int); insert into code values (100), (200)'"查看两个从库是否同步了该表以及数据docker exec mysql_slave sh -c "export MYSQL_PWD=111; mysql -u root mydb -e 'select * from code \G'"docker exec mysql_slave2 sh -c "export MYSQL_PWD=111; mysql -u root mydb -e 'select * from code \G'"如果前边的安装正确的话, 就可以看到第一步插入的两条数据了相关命令查看docker-compose运行日志docker-compose logs查看运行的docker容器docker-compose ps查看主库运行状态docker exec mysql_master sh -c 'mysql -u root -p111 -e "SHOW MASTER STATUS \G"'查看从库运行状态docker exec mysql_slave sh -c 'mysql -u root -p111 -e "SHOW SLAVE STATUS \G"'docker exec mysql_slave2 sh -c 'mysql -u root -p111 -e "SHOW SLAVE STATUS \G"'进入主库docker exec -it mysql_master bash进入从库docker exec -it mysql_slave bashdocker exec -it mysql_slave2 bash

November 5, 2019 · 1 min · jiezi

Redis的主从复制MasterSlave

一、是什么主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slave机制,Master以写为主,Slave以读为主 二、能干啥读写分离 容灾备份 三、怎么配配从(库)不配主(库)从库配置:slaveof 主库IP 主库端口每次与master断开后,都需要重新连接,除非你配置进redis.conf文件info replication修改配置文件细节操作拷贝多个redis.conf文件开启daemonize yesPid文件名字指定端口log文件名字Dump.rdb名字四、 一主二从模式 slaveof 127.0.0.1 6379 // 通过此命令,使6380,6381服务作为6379的从机五、 薪火相传模式slaveof 127.0.0.1 6379 // 通过此命令,使6380作为6379的从机slaveof 127.0.0.1 6380 // 通过此命令,使6381作为6380的从机六、 反客为主模式基于一主二从模式,主机挂了,两个从机中选一个作为新主机 slaveof no one // 选为主机七、复制原理Slave启动成功连接到master后会发送一个sync命令Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕后,master将传送整个数据文件到slave,以完成一次完全同步全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。增量复制:Master继续将新的所有收集到的修改命令一次传给slave, 完成同步但只有是重新连接master,一次完全同步(全量复制)将会被自动执行 八、哨兵模式是什么反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库怎么配基于一主二从,6379带着6380,6381在redis配置文件目录新建sentinel.conf 文件sentinel monitor 被监控数据库名字(自己起名字)127.0.0.1 6379 1最后一个1,表示主机挂了后,slave投票看谁接替成为主机,得票数多少后成为主机启动哨兵,redis-sentinel /etc/redis/sentinel.conf一组sentinel能同时监控多个Master

October 8, 2019 · 1 min · jiezi

MySQL主从同步中的serverid

当我们搭建MySQL集群时,自然需要完成数据库的主从同步来保证数据一致性。而主从同步的方式也分很多种,一主多从、链式主从、多主多从,根据你的需要来进行设置。但只要你需要主从同步,就一定要注意server-id的配置,否则会出现主从复制异常。 在控制数据库数据复制和日志管理中,有两个重要的配置:server-id和server-uuid,他们会影响二进制日志文件记录和全局事务标识。 server-id配置 当你使用主从拓扑时,一定要对所有MySQL实例都分别指定一个独特的互不相同的server-id。默认值为0,当server-id=0时,对于主机来说依然会记录二进制日志,但会拒绝所有的从机连接;对于从机来说则会拒绝连接其它实例。 MySQL实例的server-id是一个全局变量,可以直接查看: mysql> show variables like '%server_id%';+---------------+-----------+| Variable_name | Value |+---------------+-----------+| server_id | 171562767 |+---------------+-----------+1 row in set (0.00 sec)我们可以在线直接修改全局变量server-id,但不会立即生效,所以修改后记得重启服务。而重启后又会重新读取系统配置文件配置,导致刚才的修改失效,因此建议修改配置文件后重启服务而不是在线修改: #my.cnf[mysqld]#replicationlog-bin=mysql-binserver-id=171562767sync_binlog=1binlog-ignore-db=mysqlbinlog-ignore-db=information_schemaserver-id用途server-id用于标识数据库实例,防止在链式主从、多主多从拓扑中导致SQL语句的无限循环: 标记binlog event的源实例过滤主库binlog,当发现server-id相同时,跳过该event执行,避免无限循环执行。如果设置了replicate-same-server-id=1,则执行所有event,但有可能导致无限循环执行SQL语句。我们用两个例子来说明server-id为什么不要重复: 当主库和备库server-id重复时由于默认情况replicate-same-server-id=0,因此备库会跳过所有主库同步的数据,导致主从数据的不一致。 当两个备库server-id重复时会导致从库跟主库的连接时断时连,产生大量异常。根据MySQL的设计,主库和从库通过事件机制进行连接和同步,当新的连接到来时,如果发现server-id相同,主库会断开之前的连接并重新注册新连接。当A库连接上主库时,此时B库连接到来,会断开A库连接,A库再进行重连,周而复始导致大量异常信息。 生成server-id的规则既然server-id不能相同,而当我们有10个实例时,怎么保证每个都不同呢?有几种常用的方法: 随机数时间戳IP地址+端口在管理中心集中分配,生成自增ID上面的这些方法都可以,但是注意不要超过了最大值2^32-1,同时值最好>2。我采用的方法是IP地址后两位+本机MySQL实例序号,但如果是通过docker来进行管理多实例时,这个怎么生成大家可以想下有没有什么优美的解决方案。 server-uuid配置 MySQL服务会自动创建并生成server-uuid配置: 读取${data_dir}/auto.cnf文件中的UUID如果不存在,自动创建文件和生成新的UUID并读取shell> cat ~/mysql/data/auto.cnf[auto]server-uuid=fd5d03bc-cfde-11e9-ae59-48d539355108这个auto.cnf配置风格类似于my.cnf,但这个文件只包含一个auto配置块和一行server-uuid配置。它是自动创建的,因此不要修改它的内容。 在主从拓扑中,主从可以知道互相的UUID,在主机上使用show slave hosts,在从机上使用show slave status查看Master_UUID字段。 server-uuid参数并不能取代server-id,他们有不同的作用。当主从同步时如果主从实例的server-uuid相同会报错退出,不过我们可以通过设置replicate-same-server-id=1来避免报错(不推荐)。 参考资料17.1.6 Replication and Binary Logging Options and Variables:https://dev.mysql.com/doc/ref...如何生成唯一的server Id:http://ju.outofmemory.cn/entr...

September 7, 2019 · 1 min · jiezi

ECS实例搭建阿里云RDS实例的从库

准备工作1、安装mysql,版本要和RDS实例的版本一致; 2、安装mysql备份恢复工具percona-xtrabackup,下载地址为https://www.percona.com/downl…3、rds上创建一个普通账户,无需分配任何库的权限,用于从库同步使用; 4、添加ecs实例IP至RDS白名单;5、下载RDS的全量备份至ECS实例,全量备份坐标见下图;从备份数据恢复1、添加下述参数至mysql配置文件的[mysqld]标签下;server-id = 2156239584log-bin=mysql-binrelay-log=relay-bingtid_mode=onenforce_gtid_consistency=onbinlog_format=row log_slave_updates=12、解压下载的全量备份至临时目录,自己可以随意指定,本文指定为/data/tmp3、恢复数据innobackupex –apply-log /data/tmp/innobackupex –copy-back /data/tmp/4、修改mysql配置文件为跳过授权,即添加下述配置至[mysqld]标签下skip-grant-tables如下图所示5、修改mysql数据文件夹的属主为mysql用户,我的mysql数据是放在/data/mysql,如果不特殊指定的话是在/var/lib/mysqlchown -R mysql. /data/mysql6、启动mysql服务service mysqld start7、清空mysql库下的slave相关表信息use mysql;truncate slave_gtid_info;truncate slave_master_info;truncate slave_relay_log_info;truncate slave_worker_info;8、修改root账户密码update mysql.user set password=password(‘Your_password’) where user=‘root’;9、注释或删除跳过授权表的配置并重新启动mysql,如下图所示service mysqld restart8、配置主从再次登录mysql数据库时请指定-h 127.0.0.1reset slave;change master to master_host=‘rm-xxxxxxxx.mysql.rds.aliyuncs.com’,master_port=3306,master_user=‘xxxxxxxx’,master_password=‘xxxxxxxx’,master_auto_position=0;主库的二进制文件名及当前备份的position编号记录在/data/tmp/xtrabackup_slave_filename_info,如下图复制下述语句时注意去除MATSER_LOG_POS后面值两边的单引号CHANGE MASTER TO MASTER_LOG_FILE=‘mysql-bin.000409’, MASTER_LOG_POS=95322;最后一步就是启动同步,并查看同步状态start slave;show slave status\G;确认Slave_IO_Running、Slave_SQL_Running的值均为Yes即可,如下图所示注意点按照上述步骤操作完成后,mysql这个库是不会和RDS同步的,也就意味着从库的账户和授权和RDS没有任何关系,原因为恢复后slave的配置中配置忽略mysql库,如下图所示

March 15, 2019 · 1 min · jiezi

MySQL 配置参数 -- logs-slave-updates

logs-slave-updates 参数主要在多主多从的集群架构中开启,否则会导致各从实例无法完整同步集群的全量数据的问题。多主多从集群架构:masterA → slaveA↑ ↓masterB → slaveBlogs-slave-updates:Normally, a slave does not log to its own binary log any updates that are received from a master server. This option tells the slave to log the updates performed by its SQL thread to its own binary log.即,正常情况下,一个slave节点是不会将其从master节点同步的数据更新操作记录至自己的二进制日志bin-log中的。在多主的场景下,各master节点其实又相互作为另一方的slave节点进行着数据的一致性同步操作。例如 masterA 会以slave的角色同步 masterB 上的数据,masterB 也会以slave的角色同步 masterA 上的数据,如果没有开启 logs-slave-updates参数配置,则masterA \ masterB 虽然也能保证数据的一致性和完整性,但二者的 bin-log 中都只记录了作用在自身实例上的数据更新操作。例如:masterA insert row1 bin-logA add row1masterB insert row2 bin-logB add row2masterA replicate row2 from masterB But bin-logA will not log this updatemasterB replicate row1 from masterA But bin-logB will not log this updateslaveA replicate row1 form bin-logAslaveB replicate row2 form bin-logB因为主从复制是使用 bin-log 完成的,masterA masterB 互补同步数据时并没有从对方同步的数据写入自己的bin-log,则会导致自己的从实例只能同步到集群的部分数据。多从一从在多主一从模式下,logs-slave-updates就没那么必须了,各主实例只需维护好自身的 bin-log,从实例则分别读取各主实例的bin-log汇总集群的全量数据,还可以一定层度上提高集群性能。但为了保证容灾恢复,还是要尽可能的保证logs-slave-updates的开启,否则每台主实例都只有自身数据更新的bin-log,都只能恢复集群数据的一部分,虽然也可以只恢复各自的bin-log再全量同步其他主实例的数据,但相对麻烦些。 ...

March 14, 2019 · 1 min · jiezi

MySQL主从同步机制和同步延时问题追查

今天遇到一个问题,Mysql持续报错,主从同步延时数过大或错误。所以这篇文章给大家分享下主从同步的机制原理以及问题排查思路。故障表现最直观的表现为:mysql> show slave status\G; // 状态一 Seconds_Behind_Master: NULL // 状态二 Seconds_Behind_Master: 0 // 状态三 Seconds_Behind_Master: 79连续查询,大部分时间该属性值=0,偶发性出现Null或者79等延时值。导致观察主从同步延时的监控持续报警。故障原因及解决方案多台备机的server-id一致,导致主机无法长时间同某一台备机连接,进而无法正常同步。修改server-id后,重启数据库恢复。主从同步机制MySQL的主从同步,又称为复制(replication),是一种内置的高可用高性能集群解决方案,主要功能有:数据分布:同步不需要很大带宽,可以实现多数据中心复制数据。读取的负载均衡:通过服务器集群,可以通过DNS轮询、Linux LVS等GSLB(全局负载均衡)方式,降低主服务器的读压力。数据库备份:复制是备份的一部分,但并不能代替备份。还需要与快照相结合。高可用性和故障转移:从服务器可以快速切换为主服务器,减少故障的停机时间和恢复时间。主从同步分为3步:主服务器(master)把数据更改记录到二进制日志(binlog)中。从服务器(slave)把主服务器的二进制日志复制到自己的中继日志(relay log)中。从服务器重做中继日志中的日志,把更改应用到自己的数据库上,达到数据的一致性。主从同步是一个异步实时的同步,会实时的传输,但存在执行上的延时,如果主服务器压力很大,延时也会相应扩大。通过上面的图,可以看到一共需要3个线程:主服务器的日志传送线程:负责将二进制日志增量传送到备机从服务器的I/O线程:负责读取主服务器的二进制日志,并保存为中继日志从服务器的SQL线程,负责执行中继日志查看MySQL线程我们可以使用show full processlist;命令来查看MySQL的状态:主机的状态:备机的状态:可以看到,我的集群架构为1台主机、4台备机,所以在主机中有4个同步线程(已经发送所有的binlog数据到备机,等待binlog日志更新),1个查看命令线程(show full processlist)。在备机中有1个查看命令线程,1个I/O线程(等待主机发送同步数据事件),1个SQL线程(已经读取了所有中继日志,等待I/O线程来更新它)。查看同步状态因为主从同步是异步实时的,也就是会存在延时的情况,我们可以通过show slave status;来查看备机上的同步延时:在主从同步中我们需要关注的一些属性,已经给大家标红了:Slave_IO_State: 当前I/O线程的状态Master_Log_File: 当前同步的主服务器的二进制文件Read_Master_Log_Pos: 当前同步的主服务器的二进制文件的偏移量,单位为字节,如图中为已经同步了12.9M(13630580/1024/1024)的内容Relay_Master_Log_File: 当前中继日志同步的二进制文件Slave_IO_Running: 从服务器中I/O线程的运行状态,YES为运行正常Slave_SQL_Running: 从服务器中SQL线程的运行状态,YES为运行正常Exec_Master_Log_Pos: 表示同步完成的主服务器的二进制日志偏移量Seconds_Behind_Master: 表示从服务器数据比主服务器落后的持续时长同样可以通过show master status;命令来查看主服务器的运行状态:正常运行的主从同步状态:Slave_IO_Running: YESSlave_SQL_Running: YESSeconds_Behind_Master: 0问题排查在理解了主从同步的机制后,再来看今天遇到的问题,通过查看备机状态,我们观察在三种状态下的几个关键属性值:mysql> show slave status\G;#状态一: Slave_IO_State: Reconnecting after a failed master event read Slave_IO_Running: No Slave_SQL_Running: Yes Seconds_Behind_Master: NULL#状态二: Slave_IO_State: Waiting for master to send event Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0#状态三: Slave_IO_State: Queueing master event to the relay log Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 636通过MySQL主从复制线程状态转变,我们可以看到三种状态的不同含义:# 状态一# 线程正尝试重新连接主服务器,当连接重新建立后,状态变为Waiting for master to send event。Reconnecting after a failed master event read# 状态二# 线程已经连接上主服务器,正等待二进制日志事件到达。如果主服务器正空闲,会持续较长的时间。如果等待持续slave_read_timeout秒,则发生超时。此时,线程认为连接被中断并企图重新连接。Waiting for master to send event# 状态三# 线程已经读取一个事件,正将它复制到中继日志供SQL线程来处理。Queueing master event to the relay log在这里,我们可以猜测,由于某些原因,从服务器不断的和主服务器进行断开并尝试重连,重连成功后又再次断开。我们再看看主机的运行情况:发现问题出在10.144.63.*和10.144.68.*两台机器上,我们查看其中一台的错误日志:190214 11:33:20 [Note] Slave: received end packet from server, apparent master shutdown: 190214 11:33:20 [Note] Slave I/O thread: Failed reading log event, reconnecting to retry, log ‘mysql-bin.005682’ at postion 13628070拿到关键字Slave: received end packet from server, apparent master shutdown: Google搜索一下,在文章Confusing MySQL Replication Error Message中可以看到原因为两台备机的server-id重复。One day it happen to me, and took me almost an hour to find that out.Moving foward I always use a base my.cnf to I copy to any other server and the first thing is to increase the server-id.Could MySQL just use the servername intead of a numeric value?问题修复定位了问题,我们确认下是否重复,发现两台备机的该字段确实相同:vim my.cnf#replicationlog-bin=mysql-bin# 这个随机数字相同导致的server-id=177230069sync_binlog=1更改一个其他不同的数字,保存,重启MySQL进程,报警恢复。总结最终来看,这个问题的解决非常简单,但从刚开始的迷茫到最后的思路清晰,都是我们排查问题所常见的,这篇文章的主要收获是让你明白主从同步的机制和追查问题的思路,希望下次我们都能很快的解决主从同步带给我们的问题。参考资料《MySQL基础内幕 InnoDB存储引擎 第2版》P8.7 复制MySQL主从复制线程状态转变: http://www.ywnds.com/?p=3821Confusing MySQL Replication Error Message: https://www.percona.com/blog/… ...

February 14, 2019 · 1 min · jiezi