01 背景
之所以引入主从复制,是基于实际业务需求考虑的:
1、存在这样的一种场景:有一句SQL语句需要锁表,导致系统暂时无法提供读服务,这样就很影响运行中的业务,如果使用主从复制,让主库负责写操作,从库负责读操作,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作;
2、从库可以做数据的热备;
3、架构的扩展,业务量越来越大,I/O访问频率过高,单机无法满足,此时多从库存储,可以提高单个机器的I/O性能。
02 概述
复制是指将主数据库的DDL和DML操作通过二进制日志传到复制服务器(也叫从库)上,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。
MySQL支持一台主库同时向若干台从库进行复制,从库同时也可以作为其他服务器的主库,实现链式的复制。
优点:
1、如果主库出现问题,可以快速切换到从库提供服务;
2、可以在从库上执行查询操作,降低主库的访问压力;
3、可以在从库上执行备份,以避免备份期间影响主库的服务。
注意:
MySQL实现的是异步复制,主从库之间存在一定的差距,在从库上进行的查询操作需要考虑到这些数据的差异,一般只有更新不频繁的数据或者对实时性要求不高的数据可以通过从库查询,实时性要求高的数据仍然需要从主数据库获得。
缺点:
主从复制也带来其他一系列性能瓶颈问题:
1、写入无法扩展;
2、写入无法缓存;
3、复制延时;
4、锁表率上升;
5、表变大,缓存率下降。
03 复制拓扑
复制存在多种拓扑结构:一主库多备库,主-主复制,环形复制,树或金字塔形等,比较常见的有3种:一主多从复制架构、多级复制架构和双主复制/Dual Master架构。
3.1 一主多从复制架构
在主库读请求压力比较大的情况下,可通过配置一主多从复制架构实现读写分离,即主库主要负责处理写请求,大量对实时性要求不是特别高的读请求通过负载均衡分布到多个从库上,从而降低主库的压力。
在主库出现异常宕机的情况下,可以把一个从库切换为主库继续提供服务。
3.2 多级复制架构
一主多从的架构能够解决大部分读请求压力特别大的场景的需求,但是由于MySQL的复制是主库“推送”Binlog日志到从库,主库的I/O压力和网络压力会随着从库的增加而增长,为了解决主库IO和网络压力大的问题,引入多级复制架构。
多级复制架构是在主库master1复制到从库slave1、slave2、slave3的中间增加一个二级主库master2,主库只需要给一个从库master2“推送”binlog日志即可,减轻主库master1的压力(主库master1从原来推送3次减少为推送1次)。二级主库master2再“推送”binlog日志给从库slave1、slave2、slave3。
多级复制架构是异步复制,多级复制场景下主库的数据是经历两次复制才到达从库的,期间的延时比一主多从复制场景下只经历一次复制的要大。
3.3 双主复制/Dual Master复制
双主/Dual Master架构特别适用于DBA做维护等需要主从切换的场景,通过双主/Dual Master架构避免了重复搭建从库的麻烦。
04 原理
MySQL复制原理大致如下:
1、首先,MySQL主库在事务提交时会把数据变更作为事件Events记录在二进制日志文件binlog中,MySQL主库上的sync_binlog参数控制binlog日志刷新到磁盘;
2、主库推送二进制日志文件binlog中的事件到从库的中继日志Relay Log,之后从库根据中继日志Relay Log重做数据变更操作,通过逻辑复制以此来达到主库和从库的数据一致。
4.1 过程
MySQL通过3个线程来完成主从库间的数据复制:其中Binlog Dump线程跑在主库上,I/O线程和SQL线程跑在从库上。
当在从库上启动复制(START SLAVE)时,首先创建I/O线程连接主库,主库随后创建Binlog Dump线程读取数据库事件并发送给I/O线程,I/O线程获取到事件数据后更新到从库的中继日志Relay Log中去,之后从库上的SQL线程读取中继日志Relay Log中更新的数据库事件并应用。
注:中继日志文件Relay Log的文件格式、内容和二进制日志文件binlog一样,唯一的区别在于从库上的SQL线程在执行完当前中继日志文件Relay Log中的事件之后,SQL线程会自动删除当前中继日志Relay Log,避免从库上的中继日志文件占用过多的磁盘空间。
4.2 复制方式
1、异步复制
MySQL默认的复制是异步复制。
主库在执行完客户端提交的事务后会立即将结果返回客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,如果主库崩溃,主库已经提交的事务可能并没有传到从库,如果强行将从库提升为主库,可能导致新主上的数据不完整。
2、同步复制
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
3、半同步复制
MySQL支持半同步复制。
在MySQL5.5之前,MySQL的复制是异步操作,主库和从库的数据之间存在一定的延迟,这样存在一个隐患:当在主库上写入一个事务并提交成功,而从库尚未得到主库推送的Binlog日志时,主库宕机了,例如主库磁盘损坏、内存故障等造成主库上该事务binlog丢失,此时从库可能损失这个事务,从而造成数据不一致。
为了解决这个问题,MySQL5.5引入了半同步复制机制。在MySQL5.5之前的异步复制时,主库执行完commit提交操作后,在主库写入binlog日志后即可成功返回客户端,无需等待Binlog日志传送给从库。而半同步复制时,为了保证主库上的每一个binlog事务都能够被可靠的复制到从库上,主库在每次事务成功提交时,并不及时反馈给前端应用用户,而是等待其中一个从库也接收到binlog事务并成功写入到中继日志后,主库才返回commit操作成功给客户端。半同步复制保证了事务成功提交后,至少有两份日志记录,一份在主库的binlog日志上,一份在至少一个从库的中继日志Relay Log上,从而更进一步保证了数据的完整性。
半同步复制很大程度上取决于主从库之间的网络情况,往返时延RTT(Round-Trip Time)越小决定了从库的实时性越好。通俗地说,主从库之间网络越快,从库越实时。
05 类型
5.1 基于binlog二进制日志的复制
master用户写入数据,生成event记到binary log中。slave接收master上传来的binlog,然后按顺序应用,重现master上的操作。
可以通过show variables查看binlog格式,binlog支持statement、row、mixed三种格式,也对应了MySQL的三种复制技术。
二进制日志文件binlog的格式有以下3种:
Statement:基于SQL语句级别的binlog,每条修改数据的SQL都会保存在binlog中,存储日志量是最小的。
Row:基于行级别,记录每一行数据的变化,也就是将每行数据的变化都记录到binlog中,记录得非常仔细,但并不记录原始SQL,存储event数据,存储日志量大,但是不能很直接的进行读取;在复制的时候,并不会因为存储过程或触发器造成主从库数据不一致的问题,但是记录的日志量较statement格式要大得多。
Mixed:混合statement和row模式,默认情况下采用statement模式记录,某些情况下会切换到row模式。如果每天数据操作量很大,产生的日志比较多,可以考虑选择使用mixed格式。
注:Row格式比Statement格式更能保证从库数据的一致性(复制的是记录,而不是单纯操作SQL)。当然,Row格式下的Binlog的日志量很可能会增大非常多,在设置时需要考虑磁盘空间问题。
5.2 使用GTID完成基于事务的复制
主从切换后,在传统方式里,需要找到binlog和POS点,然后执行change master to指向新的主库。对于不是很有经验的运维人员来说,往往会找错,造成主从同步复制报错,在MySQL5.6版本里,无须再找binlog和POS点,只需要知道master的IP、端口、账号和密码即可,因为同步复制是自动的,MySQL会通过内部机制GTID(Global Transaction ID)自动找点同步。
工作原理:
1、master更新数据时,会在事务前产生GTID,一同记录到binlog日志中;
2、slave端的i/o线程将变更的binlog,写入到本地的relay log中;
3、sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录;
4、如果有记录,说明该GTID的事务已经执行,slave会忽略;
5、如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog;
6、在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。
优点:
1、一个事务对应一个唯一ID,一个GTID在一个服务器上只会执行一次;
2、GTID是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置;
3、减少手工干预和降低服务故障时间,当主机挂了之后通过软件从众多的备机中提升一台备机为主机。
缺点:
1、不支持非事务引擎;
2、不支持create table ... select 语句复制;
3、不允许一个SQL同时更新一个事务引擎表和非事务引擎表;
4、在一个复制组中,必须要求统一开启GTID或者是关闭GTID;
5、开启GTID后,就不再使用原来的传统复制方式;
6、对于create temporary table 和 drop temporary table语句不支持;
7、不支持sql_slave_skip_counter。
06 备机状态
当主从复制正在进行中时,如果想查看从库两个线程运行状态,可以通过执行在从库里执行”show slave status\G”语句,可以通过输出信息获取备机状态信息:
Master_Log_File:上一个从主库拷贝过来的binlog文件
Read_Master_Log_Pos:主库binlog文件被拷贝到从库的relaylog中的位置
Relay_Master_Log_File:SQL线程当前处理中的relaylog文件
Exec_Master_Log_Pos:当前binlog文件正在被执行的语句的位置
网友评论