MySQL主从复制
原理:将主服务器的binlog日志
复制到从服务器上执行一遍
,达到主从数据的一致
状态。
从一个MySQL数据库服务器主节点复制到一个或多个从节点
。MySQL 默认采用异步复制
方式,这样从节点不用一直访问主服务器
来更新自己的数据,数据的更新可以在远程连接上进行,从节点可以复制主数据库中的所有数据库或者特定的数据库
过程:从库开启一个I/O线程,向主库请求Binlog日志
。主节点开启一个binlog dump线程
,检查
自己的bin log二进制日志
,并发送给从节点
;从库将接收到的数据保存到中继日志(Relay log)中
,另外开启一个SQL线程
,把Relay log中的操作在自身机器上执行
一遍
优点:
作为备用数据库
,并且不影响业务
可做读写分离
,一般是一个写库,一个或多个读库,分布在不同的服务器上
,充分发挥服务器和数据库的性能,但要保证数据的一致性
扩展:
SQL线程执行完Relay log中的事件后,会将当前的中继日志Relay log删除,避免它占用更多的磁盘空间
为保证从库重启后,仍然知道从哪里开始复制
,从库默认会创建两个文件master.info和relay-log.info,分别记录了从库的IO线程当前读取主库binlog的进度
和SQL线程应用Relay-log的进度
。可通过show slave status \G命令查看从库当前复制的状态
解析
MySQL主从复制涉及到三个线程,一个运行在主节点(log dump thread
),其余两个(I/O thread, SQL thread)运行在从节点
,如下图所示
主节点 binary log dump 线程
当从节点连接主节点时,主节点会创建一个log dump 线程
,用于发送bin-log的内容
。在读取bin-log中的操作时,此线程会对主节点上的bin-log加锁,当读取完成,在发送给从节点之前,锁会被释放
。
异步复制的优点就是速度快,但当网络卡顿时,有可能导致数据不能完全同步。
从节点I/O线程
当从节点上执行start slave命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的bin-log
。I/O线程接收到主节点binlog dump 进程发来的更新之后,保存在本地relay-log中
。
从节点SQL线程
SQL线程负责读取relay log中的内容
,解析成具体的操作并执行
,最终保证主从数据的一致性。
复制的基本过程如下:
从节点上的I/O 进程连接主节点
,并请求从指定日志文件
的指定位置
(或者从最开始的日志)之后的日志内容
;主节点接收到来自从节点的I/O请求后
,通过负责复制的I/O进程根据请求信息读取指定日志指定位置之后的日志信息
,返回给从节点
。返回信息中除了日志所包含的信息之外,还包括本次返回的信息的bin-log file
的以及bin-log position
;- 从节点的I/O进程接收到内容后,将
接收到的日志内容更新到本机的relay log
中,并将读取到的binary log文件名和位置保存到master-info 文件
中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log 的哪个位置开始往后的日志内容,请发给我”
; - Slave 的
SQL线程检测到relay-log 中新增加了内容后
,会将relay-log的内容解析成在主节点上实际执行过的操作,并在本数据库中执行
。
复制架构
一主多从架构
主库的请求压力非常大
时,可通过配置一主多从复制架构实现读写分离
,把大量对实时性要求不是很高的请求通过负载均衡分发到多个从库上去读取数据,降低主库的读取压力
。而且在主库出现宕机时,可将一个从库切换为主库继续提供服务
多级复制架构
因为每个从库在主库上都会有一个独立的Binlog Dump线程来推送binlog日志
,所以随着从库数量的增加
,主库的IO压力和网络压力也会随之增加
,这时,多级复制架构应运而生。
多级复制架构只是在一主多从的基础上,再主库和各个从库之间增加了一个二级主库Master2
,这个二级主库仅仅用来将一级主库推送给它的BInlog日志再推送给各个从库,以此来减轻一级主库的推送压力
。
但它的缺点就是Binlog日志要经过两次复制才能到达从库,增加了复制的延时。
我们可以通过在二级从库上应用Blackhol存储引擎(黑洞引擎)来解决这一问题,降低多级复制的延时。
“黑洞引擎”就是写入Blackhole表中数据并不会写到磁盘上,所以这个Blackhole表永远是个空表,对数据的插入/更新/删除操作仅在Binlog中记录,并复制到从库中去。
双主复制/Dual Master架构
双主复制架构适用于需要进行主从切换
的场景
在只有一个主库的架构下,当主库宕机后,将其中一个从库切换为主库继续提供服务
。原来的主库就没有数据来源了,那么当这个新的主库接收到新的数据时,原来的主库却没有同步,因此他们的数据差异越来越大
,那么原来的主库就无法成为主从复制环境中的一员了。当原来的主库恢复正常后,需要重新将其添加进复制环境中去
。
那为了避免重复添加主库的问题,双主复制应运而生。两个数据库互为主从,当主库宕机恢复后,由于它还是原来从库(现在主库)的从机,所以它还是会复制新的主库上的数据
。那么无论主库的角色怎么切换,原来的主库都不会脱离复制环境。
复制方式
异步复制
在异步复制中,主库执行完操作后,写入binlog日志后,就返回客户端,这一动作就结束了,并不会验证从库有没有收到,完不完整,所以这样可能会造成数据的不一致
。
说到底,复制过程中数据是否一致,主要取决于Binlog日志的安全性与完整性
为了更加有效的保护Binlog的安全性和完整性
,MySQL5 .5之后引入了半同步复制
半同步复制
在异步复制中,我们遇到的一个主要问题就是,在复制过程当中,主库不会去验证Binlog有没有成功复制到从库,那如果主库提交一个事务并写入Binlog中后,当从库还没有从主库得到Binlog时,主库宕机了或因磁盘损坏等故障导致该事务的Binlog丢失了,那从库就不会得到这个事务,也就造成了主从数据的不一致
。
而半同步复制,当主库每提交一个事务后,不会立即返回,而是等待其中一个从库接收到Binlog并成功写入Relay-log中才返回客户端,所以这样就保证了一个事务至少有两份日志,一份保存在主库的Binlog,另一份保存在其中一个从库的Relay-log
中,从而保证了数据的安全性和一致性。
另外,在半同步复制时,如果主库的一个事务提交成功了,在推送到从库的过程当中,从库宕机了或网络故障,导致从库并没有接收到这个事务的Binlog
,此时主库会等待一段时间
(这个时间由rpl_semi_sync_master_timeout的毫秒数决定),如果这个时间过后还无法推送到从库,那MySQL会自动从半同步复制切换为异步复制
,当从库恢复正常连接到主库后,主库又会自动切换回半同步复制。
半同步复制的“半”体现在,虽然主从库的Binlog是同步的,但主库不会等待从库执行完Relay-log后才返回,而是确认从库接收到Binlog,达到主从Binlog同步的目的后就返回了
,所以从库的数据对于主库来说还是有延时的,这个延时就是从库执行Relay-log的时间
。所以只能称为半同步。