一、为什么要做主从同步

1.读写分离,降低对主数据库的IO消耗

2.避免数据丢失

3.提高业务系统性能

二、主从同步和集群的区别

1.主从同步

一般需要两台及以上数据库服务器即可(一台用于写入数据,一台用于同步主的数据并用于数据查询操作)。

2.集群

集群是由N台数据库服务器组成,数据的写入和查询是随机到任意一台数据库服务器的,其他数据库服务器会自动同步数据库的操作。

任何一台数据库宕机,不会对整个集群造成大的影响。

三、复制的概念

Mysql内建的复制功能是构建大型,高性能应用程序的基础。将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重新执行一遍来实现的。复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。

四、复制的模式

按类型分为以下三种:

1.基于语句的复制:

在主服务器上执行的SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。一旦发现没法精确复制时,会自动选着基于行的复制。

2.基于行的复制:

把改变的内容复制过去,而不是把命令在从服务器上执行一遍. 从mysql5.0开始支持

3.混合类型的复制:

默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。

按机制分为以下三种:

1.异步复制:

从主机拷贝到备机过程中会有延迟,延迟通常由网络、资源可用性和系统负载来决定。使用合适架构和调优,大多复制几乎是瞬间完成的。

2.同步复制:

数据同时向一台或多台机器提交,保证多系统一致性,但也会带来额外性能损失,mysql本身不支持同步复制,利用分布式复制块设备技术能提供同步复制功能。

3.半同步复制:

MySQL5.5新功能,主机提交半同步到从机,从机收到事务所有事件后返回给主机确认该事务提交完成或超时。当发生超时,主机会使用异步复制。半同步复制保障主机所有已提交事务都被复制到从机。

  • 5.5集成到mysql,以插件的形式存在,需要单独安装
  • 确保事务提交后binlog至少传输到一个从库
  • 不保证从库应用完这个事务的binlog
  • 性能有一定的降低,响应时间会更长
  • 网络异常或从库宕机,卡主主库,直到超时或从库恢复

五、复制架构

1、单向主从复制逻辑图

2、双向主主同步逻辑图,此架构可以在Master1端或Master2端进行数据写入

3、线性级联单向双主同步逻辑图,此架构只能在Master1端进行数据写入

4、环状级联单向多主同步逻辑图,任何一个点都可以写入数据

5、环状级联单向多主多从同步逻辑图,此架构只能在任意一个Master端进行数据写入

6、官方推荐架构图

六、复制原理

master服务器将数据的改变记录到二进制binlog日志中,当master上的数据发生改变时,则将其改变写入二进制日志中;salve服务器会在一定时间间隔内对master二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/OThread请求master二进制事件,同时主节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至从节点本地的中继日志中,从节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致,最后I/OThread和SQLThread将进入睡眠状态,等待下一次被唤醒。

在Master与Slave之间实现整个主从复制的过程是由三个线程参与完成的。其中有两个线程(SQL线程和IO线程)在Slave端,另一个线程(I/O线程)在Master端。

下图为复制过程:



1)在Slave 服务器上执行sart slave命令开启主从复制开关,开始进行主从复制。

2)此时,Slave服务器的IO线程会通过在master上已经授权的复制用户权限请求连接master服务器,并请求从执行binlog日志文件的指定位置(日志文件名和位置就是在配置主从复制服务时执行change

master命令指定的)之后开始发送binlog日志内容

3)Master服务器接收到来自Slave服务器的IO线程的请求后,其上负责复制的IO线程会根据Slave服务器的IO线程请求的信息分批读取指定binlog日志文件指定位置之后的binlog日志信息,然后返回给Slave端的IO线程。返回的信息中除了binlog日志内容外,还有在Master服务器端记录的IO线程。返回的信息中除了binlog中的下一个指定更新位置。

4)当Slave服务器的IO线程获取到Master服务器上IO线程发送的日志内容、日志文件及位置点后,会将binlog日志内容依次写到Slave端自身的Relay Log(即中继日志)文件(MySQL-relay-bin.xxx)的最末端,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取master端新binlog日志时能告诉Master服务器从新binlog日志的指定文件及位置开始读取新的binlog日志内容

5)Slave服务器端的SQL线程会实时检测本地Relay Log 中IO线程新增的日志内容,然后及时把Relay LOG 文件中的内容解析成sql语句,并在自身Slave服务器上按解析SQL语句的位置顺序执行应用这样sql语句,并在relay-log.info中记录当前应用中继日志的文件名和位置点

主从复制条件

  • 开启Binlog功能
  • 主库要建立账号
  • 从库要配置master.info(CHANGE MASTER to…相当于配置密码文件和Master的相关信息)
  • start slave 开启复制功能

注意几点:

  • master将操作语句记录到binlog日志中,然后授予slave远程连接的权限(master一定要开启binlog二进制日志功能;通常为了数据安全考虑,slave也开启binlog功能)。
  • slave开启两个线程:IO线程和SQL线程。其中:IO线程负责读取master的binlog内容到中继日志relay log里;SQL线程负责从relay log日志里读出binlog内容,并更新到slave的数据库里,这样就能保证slave数据和master数据保持一致了。
  • Mysql复制至少需要两个Mysql的服务,当然Mysql服务可以分布在不同的服务器上,也可以在一台服务器上启动多个服务。
  • Mysql复制最好确保master和slave服务器上的Mysql版本相同(如果不能满足版本一致,那么要保证master主节点的版本低于slave从节点的版本)
  • master和slave两节点间时间需同步

七、复制属性

mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: xxx.xxx.xxx.xxx
Master_User: slavebak
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.001008
Read_Master_Log_Pos: 592644582
Relay_Log_File: mysql-relay-bin.000136
Relay_Log_Pos: 8596677
Relay_Master_Log_File: mysql-bin.001008
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
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: 592644582
Relay_Log_Space: 9271830
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: 3138

Slave_IO_Running:Yes

这是I/O线程状态,I/O线程负载从从库去主库读取binlog日志,并写入从库的中继日志中,状态为Yes表示I/O线程工作正常。

Slave_SQL_Running:Yes

这个是SQL线程状态,SQL线程负载读取中继日志(relay-log)中的数据并转换为SQL语句应用到从库数据库中,状态为Yes表示I/O线程工作正常。

Seconds_Behind_Master:0

这个是在复制过程中,从库比主库延迟的描述,这个参数很重要,但企业里更准确地判断主从延迟的方法为:在主库写时间戳,然后从库读取时间戳进行比较,从而认定是否延迟。

八、复制中出现的问题汇总

1.slave运行过慢不能与master同步,也就是MySQL数据库主从同步延迟

slave滞后即slave不能快速执行来自于master的所有事件,从而不能避免更新slave数据延迟。

slave同步延迟的原理

  • MySQL的主从复制都是单线程的操作,主库对所有DDL和DML产生的日志写进binlog,由于binlog是顺序写,所以效率很高。
  • Slave的IO Thread线程从主库中bin log中读取日志。
  • Slave的SQL Thread线程将主库的DDL和DML操作事件在slave中重放。DML和DDL的IO操作是随即的,不是顺序的,成本高很多。

由于SQL Thread也是单线程的,如果slave上的其他查询产生lock争用,又或者一个DML语句(大事务、大查询)执行了几分钟卡住了,那么所有之后的DML会等待这个DML执行完才会继续执行,这就导致了延时。

也许有人会质疑:主库上那个相同的DDL也会执行几分钟,为什么slave会延时?

原因是master可以并发执行,而Slave_SQL_Running线程却不可以。

slave同步延迟的可能原因

  • slave的I/O线程推迟读取日志中的事件信息;最常见原因是slave是在单线程中执行所有事务,而master有很多线程可以并行执行事务。
  • 带来低效连接的长查询、磁盘读取的I/O限制、锁竞争和innodb线程同步启动等。
  • Master负载;Slave负载
  • 网络延迟
  • 机器配置(cpu、内存、硬盘)

主从同步延迟怎么产生的?

当主库的TPS并发较高时,产生的DDL数量超过slave一个sql线程所能处理的承受范围时,主从同步就会产生延时;或者当slave中有大型query语句产生了锁等待也会产生延时。

如何查看同步延迟

  • 可以通过比对master、slave上的日志位置。
  • 通过"show slave status"查看Seconds_Behind_Master的值,这个值代表主从同步延迟的时间,值越大说明延迟越严重。值为0为正常情况,正值表示已经出现延迟,数字越大从库落后主库越多。
  • 使用percona-toolkit的pt-hearbeat工具进行查看。

减少同步延迟的操作方案

  • 减少锁竞争

    如果查询导致大量的表锁定,需要考虑重构查询语句,尽量避免过多的锁。
  • 负载均衡

    搭建多少slave,并且使用lvs或nginx进行查询负载均衡,可以减少每个slave执行查询的次数和时间,从而将更多的时间用于去处理主从同步。
  • salve较高的机器配置
  • Slave调整参数

    为了保障较高的数据安全性,配置sync_binlog=1,innodb_flush_log_at_trx_commit=1等设置。而Slave可以关闭binlog,innodb_flush_log_at_trx_commit也可以设置为0来提高sql的执行效率(这两个参数很管用)
  • 并行复制

    即有单线程的复制改成多线程复制。

    从库有两个线程与复制相关:io_thread 负责从主库拿binlog并写到relaylog, sql_thread 负责读relaylog并执行。

    多线程的思路就是把sql_thread 变成分发线程,然后由一组worker_thread来负责执行。

    几乎所有的并行复制都是这个思路,有不同的,便是sql_thread 的分发策略。

    MySQL5.7的真正并行复制enhanced multi-threaded slave(MTS)很好的解决了主从同步复制的延迟问题。
2.slave同步状态中出现Slave_IO_Running: NO

报错:Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'

原因:清理数据导致主从库不同步。

解决办法:

1)先进入slave中执行:"slave stop;"来停止从库同步;

2)再去master中执行:"flush logs;"来清空日志;

3)然后在master中执行:"show master status;"查看下主库的状态,主要是日志的文件和position;

4)然后回到slave中,执行:"CHANGE MASTER TO ......执行同步指令

3.slave同步状态中出现Slave_IO_Running: Connecting

导致这个错误的原因一般是:

  • 网络不通
  • 权限问题(连接master的用户名和密码跟master授权不一致)
  • 连接时用的log file和pos节点跟"show master status"的结果不一致
4.slave同步状态中出现Slave_SQL_Running: No ,即slave不同步!

解决办法:

1)忽略错误后,继续同步。

该方法适用于主从库数据相差不大,或者要求数据可以不完全统一的情况,数据要求不严格的情况(下面均为在slave机器上的操作)

mysql> stop slave;
mysql> set global sql_slave_skip_counter =1;
mysql> start slave;
mysql> show slave status\G:

2)重新做主从,完全同步

该方法适用于主从库数据相差较大,或者要求数据完全统一的情况

1、master主库上操作

mysql> flush tables with read lock;
#mysqldump --lock-all-tables --all-databases --flush-logs --master-data=2 > /root/allsql.sql
mysql> show master status;
# scp mysql.bak.sql root@192.168.1.102:/tmp/ //把备份文件传到slave从库机器,进行数据恢复

2、slave从库操作

mysql> stop slave;
mysql> source /tmp/mysql.bak.sql
mysql> change master to master_host = '192.168.1.101', master_user = 'slave', master_port=3306.......;
mysql> start slave;
mysql> show slave status\G
.......
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

此种方法中最为关键主要有两步:

①主服务器上锁表做完全备份,并滚动日志;

②从服务器上进行半道恢复.

5.slave中继日志relay-log损坏?

什么是中继日志?

relay-log存放在从服务器上,从服务器将主服务器的二进制日志文件拷贝到自己的主机上放在中继日志中,然后调用SQL线程按照拷中继日志文件中的二进制日志文件执行以便就可达到数据的同步 。

如何中继日志避免:

mysql 5.6版本后,在my.cnf文件中开启relay_log_recover=1即可避免。

6.slave连接超时且重新连接频繁

若有多个slave,且没有设置server_id或两个slave设置相同的server_id,将有可能会出现服务器的ID冲突。这种情况下,其中一台slave可能会频繁超时或丢失后重新连接序列。

所以一定要确保每台slave及master在my.cnf中都要设置不一样的server_id。

7.主库与从库使用不同的存储引擎造成不同步

8.从库同步时,提示表不存在

错误:Last_Error: Error executing row event: 'Table 'test.t1' doesn't exist'

解决方法:在从库重建这张表。

9.max_allowed_packet设置过小导致slave报错

max_allowed_packet默认是16M,主从库的max_allowed_packet值和备库上的不匹配。

在这情况下,主库可能会记录一个备库认为过大的包。当备库获取到该二进制日志事件时,可能会碰到各种问题,如无限报错和重试、中继日志损坏等。

具体表现:

从库的Slave_IO_Thread死掉了,查看后,出现以下错误提示:Got a packet bigger than 'max_allowed_packet' bytes

很明显是由于max_allowed_packet的设置太小导致的,然后查检主从库上的设置,主库的设置大于从库,因为max_allowed_packet是动态参数,先调整从库上的max_allowed_packet 与主库相同,重新单独启动I/O线程就正常了。

原理说明:

binlog的事件以RBR格式记录,且当前的事件长度大于了从库的max_allowed_packet, 导致无法Slave IO不能正常读取master binlog event.

10.在master上删除一条记录时出现的故障

在master上删除一条记录后,slave上因找不到这条记录而报错。

解决方法:

由于主库上已经对这条语句进行了删除操作,故可以跳过。

在这种情况下,说明主从同步可能数据会有不一致的情况发生,所以需要使用pt-table-checksum进行数据库一致性比对。

11.在master更新一条记录,而slave却找不到。

主从数据不致时,master有某条记录,但在salve上没有这条记录,若在master上进行更新这条记录,则在slave中可能报错。

解决方法:

  • 根据从库发生异常的位置,查主库上的二进制日志。
  • 根据主库二进制日志信息,找到更新后的整条记录。
  • 在从库上执行在主库上找到的记录信息,进行insert操作。
  • 跳过这条语句,再同步slave。
  • 使用pt-table-checksum查看主从库表数据否一致。

Mysql主从复制原理详解的更多相关文章

  1. (转)MySQL备份原理详解

    MySQL备份原理详解 原文:http://www.cnblogs.com/cchust/p/5452557.html 备份是数据安全的最后一道防线,对于任何数据丢失的场景,备份虽然不一定能恢复百分之 ...

  2. MySQL备份原理详解

    备份是数据安全的最后一道防线,对于任何数据丢失的场景,备份虽然不一定能恢复百分之百的数据(取决于备份周期),但至少能将损失降到最低.衡量备份恢复有两个重要的指标:恢复点目标(RPO)和恢复时间目标(R ...

  3. mysql主从复制安装详解

    1.环境准备:两台Linux6.8服务器,(可以通过yum安装mysql:yum install mysql mysql-server -y,安装的版本可能比较低,对于练手来说够用了 )主库ip:19 ...

  4. 二十二、mysql索引原理详解

    背景 使用mysql最多的就是查询,我们迫切的希望mysql能查询的更快一些,我们经常用到的查询有: 按照id查询唯一一条记录 按照某些个字段查询对应的记录 查找某个范围的所有记录(between a ...

  5. Mysql主从复制参数详解

    目录 一.简介 二.例子 同步 修改 三.参数 一.简介 change master to配置和改变slave服务器用于连接master服务器的参数,以便slave服务器读取master服务器的bin ...

  6. mysql 复制原理详解

    http://www.cnblogs.com/kristain/articles/4142970.html

  7. TOMCAT原理详解及请求过程(转载)

    转自https://www.cnblogs.com/hggen/p/6264475.html TOMCAT原理详解及请求过程 Tomcat: Tomcat是一个JSP/Servlet容器.其作为Ser ...

  8. Mysql加锁过程详解(8)-理解innodb的锁(record,gap,Next-Key lock)

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  9. LVS原理详解(3种工作方式8种调度算法)--老男孩

    一.LVS原理详解(4种工作方式8种调度算法) 集群简介 集群就是一组独立的计算机,协同工作,对外提供服务.对客户端来说像是一台服务器提供服务. LVS在企业架构中的位置: 以上的架构只是众多企业里面 ...

随机推荐

  1. Struts2 异常处理

    Struts提供了一个更简单的方式来处理未捕获的异常,并将用户重定向到一个专门的错误页面.您可以轻松地Struts配置到不同的异常有不同的错误页面. Struts的异常处理所使用的“exception ...

  2. Eclipse Debug 调试

    Debug 调试 Java 程序 我们可以在 Package Explorer 视图调试 Java 程序,操作步骤如下: 鼠标右击包含 main 函数的 java 类 选择 Debug As > ...

  3. spark+hadoop+sqoop+hive平台bug解决方法

    bug集锦 1. hadoop平台datanode无法启动: 原因: 由于多次hdfs namenode -format导致dfs/data/current/version中的cluserID与当前的 ...

  4. Unity3D学习笔记——组件之Effects(效果/特效)——Particle System(粒子系统)

    Effects:效果/特效. Particle System:粒子系统.可用于创建烟雾.气流.火焰.涟漪等效果. 在Unity3D 3.5版本之后退出了新的shuriken粒子系统:   添加组件之后 ...

  5. Laravel5.1 路由 -路由分组

    路由分组有啥好处? 有时候啊 一大堆路由它们都有共同的地方,比如都使用一个中间件(过两天写)或是前缀都一样,避免代码重复 我们可以将他们分到一组中. 1 路由分组可以共享哪些属性? 中间件 middl ...

  6. 【Cocos游戏实战】功夫小子第八课之游戏打包和相关问题说明

    至此,功夫小子系列的Cocos2d-x的实战文章就结束了. 源代码地址: https://github.com/SuooL/KungfuBoy 如须要资源请邮件我 1020935219@qq.com ...

  7. Mysql InnoDB表结构

    索引组织表 在InnoDB存储引擎中,表都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(index organized table).在InnoDB存储引擎表中,每张表都有个主键(Prim ...

  8. 【BZOJ1923】[Sdoi2010]外星千足虫 高斯消元

    [BZOJ1923][Sdoi2010]外星千足虫 Description Input 第一行是两个正整数 N, M. 接下来 M行,按顺序给出 Charles 这M次使用“点足机”的统计结果.每行 ...

  9. 解决Initializing Java Tooling 和 Initializing Java Tooling卡死问题

    遇到了如题的问题,使用如下方法解决了 工作中eclipse崩溃,再次启动后,状态栏一直显示  Initializing Javascript Tooling . 解决方案: 删除\workspace\ ...

  10. 基于nodejs的wiki系统

    jingo:        https://github.com/claudioc/jingo nodewiki:    https://github.com/nhoss2/nodewiki Tidd ...