MySQL 主从复制那些事(一)

       本部分主要以理论为主,具体的主从搭建环境,大家可以参考博客其他部分。下面我就给大家数说主从复制那些理论的东西。说的不一定都是正确的,有不同出入的地方,欢迎大家一起交流沟通,以下我把我自己整理出来的主从复制的一些理论部分。

复制的概念
  MySQL复制就是一台MySQL服务器(slave)从另一台MySQL服务器(master)进行日志的复制然后再解析日志并应用到自身

复制的应用

      第一:是解决宕机带来的数据不一致,因为MySQL复制可以实时备份数据;
      第二:是减轻数据库服务器的压力,多台服务器的性能一般比单台要好。但是MySQL复制不适合大数据量,大数据量推荐使用集群。

 

  复制的原理图:

 

replication涉及到的三个线程

1  master上的 binlog dump(dump线程),即读取master上的binlog,发送到slave上的线程。
2  slave上的IO线程:读取slave上的relay log。
3  slave上的sql线程:执行IO线程读取的relay log的线程。

 复制相关的日志格式,提供3种格式:Row 格式(首先我们的推荐的)。mix 格式(5.7后版本把他忘记吧)statements 格式(传统的复制格式)

基于row 格式的一些优点:
  优点: 1、相比statement更加的安全复制的格式
              2、在某些情况下速度更快(SQL 复杂,表有主键)
              3、系统特殊函数也可以复制
             4、更少的锁
 缺点: Binary log 比较大(mysql-5.6 支持binlog_row_image) 
          单语句更新[删除]表的行数过多,会形成大量的binlog
          无法从binlog看见用户执行的SQL
 
基于语句 (statements )的复制优缺点:
 优点:1.Binlog 文件比较小 
            2.日志包含了用户执行的原始的SQL,方便统计和审计
           3.出现最早 binlog 兼容比较好
           4 Binlog 方便阅读方便故障的修复。
  缺点:1 存在安全的隐患 可能导致主从结构不一致
            2 对一些系统函数不能准确的复制或是不能复制
            不支持的一些复制函数LOAD_FILE() UUID(), UUID_SHORT(),USER(),FOUND_ROWS(),SYSDATE() (unless both the master and the slave are started with the --sysdate-is-now option),GET_LOCK(),IS_FREE_LOCK(),IS_USED_LOCK(),MASTER_POS_WAIT(),RAND(),RELEASE_LOCK(),SLEEP(),VERSION()
 
在主从复制的过程当中我们引入GTID的复制方式是首选。可以参考我博客里面关于GTID部分的内容。
 
小的提示:在使用ROW 格式中DDL 语句还会记录STATEMENT 格式。这个我们要注意一下。
 
 三:复制的几种类型,异步复制 ,半同步复制, 增强半同步复制,同步复制。
 
异步复制(Asynchronous replication)
  MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,
       这样就会有一个问题,主如果crash掉了,
       此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
 全同步复制(Fully synchronous replication)
  指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
半同步复制(Semisynchronous replication)
  介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。
  设置半同步:
set rpl_semi_sync_master_wait_point=AFER_COMMIT

 

无损复制优于半同步复制的原因:
        一个事务提交(commit)的过程时,在MySQL 层的write biblog 步骤后,master节点需要收到一个至少一个slave节点回复的ack(表示收到了binlog)后,才继续下一个事务;如果在一定时间内(timeout)内没有收到ack 则切换为异步模式,二进制日志(binlog) 先写远程(IO 线程接收到即可),可保证数据完全不丢失。
不丢失的半同步复制 原因是:Master 在收到salve 的ACK 应答后才Commit 事物,事物复制到slave前。并发的事物看不到当前的事物的数据当Master 故障时,所有已提交的事物都会复制到slave 上。
 无损复制性能优于半同步复制的原因
 1 就等待ACK 回包问题上,其实两种复制的开销是一样的,没有区别,都是网络的等待开销。
 2 无损复制由于在write binlog(commit的第二步)后,需要等待ACK,后续的事务无法提交,这样就堆积了很多需要落盘的事务(半同步复制由于已经提交了事务,没有堆积事务的效果),通过组提交机制,一次fsync的事务变多了(半同步复制也有组提交,只是一次fsync的事务数没那么多),相当于提高了I/O 性能所以线程(事务)越多,效果越明显。
 
1 传统的复制:异步复制是不需要等待从服务器的任何的确认信息
 

 

 2:半同步复制:
半同步复制是异步复制的升级替代的方案,可以提高数据完整性,从服务器收到更新,或者超时返回返回客户端,中间有一个ack 确认的问题。
 semi-sync replication(半同步复制):在一个事务提交的过程时,在InnoDB层的commit log步骤后,Master节点需要收到至少一个slave 节点回复的ACK (表示收到了binlog)后,
才能继续下一个事务。如果在一定时间内(timeout)内没有收到ACK,则切换为异步模式。
  • 至少有一个slave 节点收到binlog 后在返回(IO 线程接收到即可)
  •  减少数据丢失风险
  •  不能完全避免数据丢失
  • 超时后,切换回异步复制
    控制 半同步复制 还是无损复制 的参数设置:
    AFTER_SYNC 表示无损的复制(5.7 默认)
    AFTER_COMMIT 表示的是半同步复制
    rpl_semi_sync_master_wait_point=AFTER_SYNC
    至少收到1个 slave发回的ack:  rpl_semi_sync_master_wait_for_slave_count=1
 

 

 小结:
        事实上,半同步复制并不是严格意义上的半同步复制,当半同步复制发生超时时(由rpl_semi_sync_master_timeout参数控制,单位是毫秒,默认为10000,即10s),会暂时关闭半同步复制,转而使用异步复制。当master dump线程发送完一个事务的所有事件之后,如果在rpl_semi_sync_master_timeout内,收到了从库的响应,则主从又重新恢复为半同步复制
 在一主多从的架构中,如果要开启半同步复制,并不要求所有的从都是半同步复制。
     MySQL 5.7极大的提升了半同步复制的性能,独立出一个 ack collector thread ,专门用于接收slave 的反馈信息。
     这样master 上有两个线程独立工作,可以同时发送binlog 到slave,和接收slave的反馈
     低于5.7 的版本,在从库关闭一段时间后,刚启动时。注意先用异步复制,复制追上后,在用半同步复制
master:
    set global rpl_semi_sync_master_enabled=ON|OFF;
slave:
   set global  rpl_semi_sync_slave_enabled=ON|OFF;
 
要想使用半同步复制,必须满足以下几个条件
1. MySQL 5.5及以上版本
2. 变量have_dynamic_loading为YES
3. 异步复制已经存在
首先加载插件
因用户需执行INSTALL PLUGIN, SET GLOBAL, STOP SLAVE和START SLAVE操作,所以用户需有SUPER权限。
主:mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
从:mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
show plugins;查看插件是否安装成功
rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL
启动半同步复制
在安装完插件后,半同步复制默认是关闭的,这时需设置参数来开启半同步
主:mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
从:mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
 
查看半同步是否在运行:这两个变量常用来监控主从是否运行在半同步复制模式下。
主:mysql> show status like 'Rpl_semi_sync_master_status';
从:mysql> show status like 'Rpl_semi_sync_slave_status';
 
 
四:半同步常见问题:
  •  网络问题,切换到异步复制
  • 从库网络,IO 问题导致主库性能下降
  • 从库故障  利用备份还原后加入集群中,把主库拖跨
  • 复制结构中可以让binlog 备份服务保持增强半同步,如果binlog 备份能如何保持半同步,整个结构安全度会增加很多,另外要考虑复制结构中单库的约束,整个实列的大小:单实例1T左右、SAS盘 Raid10 : 单实例500G以下、单库: 200G。

五:为了增强复制引入了并行复制的概念。

在Master并发commit 事物多时,slave上并发性能越好

       为什么要引入多线程的复制,5.5 的 问题,延迟问题非常的严重,5.6 开始版本支持多线程复制,每一个库有一个独立SQL线程进行回放对于有多个库的实列有帮助,对于单实列的库依然是单线程。主从复制,多线程大大的增强了从库的能力, 5.7 版本支持多线程复制,保留基于库的多线程回放,保留基于库的多线程回放,增加根据组提交进行完全的并行复制模式,Enhanced multi-threaded slave.

 

小结:并发复制:MySQL5.6 的并发复制是基于库级别的,MySQL5.7 的并发复制是基于事物级别(logical Clock)

 实质上需要:1 让在Master 上能并发执行的事物,在Slave上也并发执行。
       2 在binlog 中记录事物并执行的相关信息
      3  slave 上根据以上这些信息,让这些事物在slave 上多个线程中并发执行
 
并行复制微调参数
  binlog_group_commit_sync_delay
  binlog_group_commit_sync_no_delay_count
  slave_preserve_commit_oder=ON|OFF
  开启binlog,Logical_clock 有作用
 
  GTID模式下启动并行复制:
stop slave sql_thread;
set global salve_parallel_workers=8;
set global slave_paralle_type="LOGICAL_CLOCK";# OR DATABASE
start slave sql_thread

 

  小结:事物能不能并行是锁来决定的,如果有锁冲突,则一个事物要等待另外一个事物执行完毕
  如何判断并行事物有没有锁的冲突?
  如果有两个事物(操作) 可以并执行,这两个事物有没有锁的冲突。
  当事物开始执行commmit 语句或者事务进入preare阶段时,它已经获取了所有的锁。
    
 实时同步:PXC 、Group-Replication 
Group Replication 实质是: 二进制日志: 基于row格式+ 全局事物标识,增强半同步 和并行复制的一个组合,可以理解成一个通信框架+事物排序控制。
 
五:为什么会出现复制延迟的问题?
            原因是复制都是基于row+gtid这样的结构运行这样会出现复制的延迟,还有另外原因就是主库出或者从库异常掉电、磁盘写入超时,进程异常crash 或者进程被kill掉。
            解决的办法:可以使用MySQL5.7+row+gtid+增强半同步
 
        关于复制延迟问题:如果遇到从库延迟,怎么定位是一个大事务造成从库延迟,排查的方法怎么做?
  show slave status\G; 查看一下我们复制的状态信息。
       发现 exec_master_log_position参数一直卡着不动。这是在复制过程会开启2个线程IO 一个是我们的IO_thread,另外一个是SQL_Thread,
       IO_thread:主要是去读取我们远程master dump 到slave 机器的 relay_log。
       观察read_master_log_file==relay_master_log_file && read_master_log_pos = exec_master_log_pos(同样适合GTID)
       如果我们的second_behind 的值是大于0的,second_behind_master  = IO_Thread.timestamp -SQL_Thread.timestamp 这时候也说明有了延迟,但是等于0也不能说就没有延迟。这个值一般是不太准确的
       自己要把握好。
 
      复制我们需要关注的几个参数:
相关的参数          
slave_IO_Running yes NO 需要关注      
slave_SQL_Running yes NO 需要关注      
seconds_behind_master 0  大于0 需要关注  单纯这个值是不能判定延迟。需要结合其他参数一起看    
last Errno & last Error 0        
  
     六:什么时候需要去校验我们的数据?
  • 主从结构其中某个节点异常的重启
  •  复制出错,修复后需要安排校验
  • 核心库或是核心,每个月为周期全部需要校验一次
  • 业务级别校验:记账类业务,基于小时级别校验及每天的整体校验
  • DBA 可以利用percona-tools去校验
 
 
 
 
 
posted @ 2018-04-08 14:55  dudochen  阅读(438)  评论(0编辑  收藏  举报