美文网首页
剖析复制线程

剖析复制线程

作者: 显卡hg | 来源:发表于2017-12-16 20:17 被阅读0次

    传统复制线程

    复制线程图
    • master
      • Dump_thread
    • slave
      • IO_Thread
      • SQL_Thread
    • 纠结的问题
      • MySQL Replication是主库把日志推给Slave,还是Slave从主库把日志拉过来的?
      • 可以这么理解,延迟时间过长,比如用备份恢复时就是拉取,正常主从没有延迟或延迟比较低时是推
      • 主从结构的瓶颈是什么?
      • sql_thread是单线程重放,master是多线程写入,容易造成瓶颈

    GTID原理

    • GTID
      • 事务唯一编号,全剧唯一(一个复制Group里)
      • 同时和事物记录到binlog中,用来标识事务
      • binlog中多一个:Gtid_log_event
    • 构成
      • UUID:sequence_number
      • sequence_number是MySQL内部的一个事务编号,一个MySQL不会重复的顺序号(保证服务器内唯一)
      • 每个MySQL有一个全局唯一的UUID:$datadir/auto.cnf中存储
      • GTID复制中出现断点,估计是使用:master_auto_position=0
    • master_auto_position=1
      • MySQL可以记录执行过的事务ID,可以通过show master status -> gtid_executed查看
      • MySQL5.6依赖于binlog和gtid_purge;MySQL5.7依赖于mysql.gtid_executed表
      • slave上记录了接收和执行的gtid,可以通过show slave status:
        • Retrieve_gtid_set
        • Execute_gtid_set
      • slave连接Master时,会把gtid_executed中的gtid发给Master,Master会Skip过executed_gtid_set,把没有执行过的GTID事务发送给slave
      • BUG:slave_net_timeout 参数设置过小,造成MySQL Master Dump thread增多,主库会认为自己多了从库,其实是频繁的从库连接又断开造成的
    • MySQL5.6从非GTID到GTID切换,需要重启
    • MySQL5.7支持在线启用GTID
      • 不用重启mysqld
      • 在启用GTID过程,可以对外提供服务
      • 不需要改变复制结构
      • 如果需要GTID,又不想太多停机时间:升级到MySQL5.7在线启用就OK
    • MySQL5.7GTID启动过程
      • gtid_mode
    gitd_mode 解释
    OFF 不产生GTID,Slave只接收不带GTID的事务
    OFF_PERMISSIVE 不产生GTID,Slave接收不带GTID的事务也接收带GTID的事务
    ON_PERMISSIVE 产生GTID,Slave接收不带GTID的事务也接收带GTID的事务
    ON 产生GTID,Slave只接收带GTID的事务
    • 5.7GTID的切换流程
    gitd_mode 执行对象
    set global gtid_mode='OFF_PERMISSIVE'; 在Group中每个MySQL上执行
    set global gtid_mode='ON_PERMISSIVE'; 在Group中每个MySQL上执行,为了安全尽量现在从库上执行
    确认每个Group中binlog非GTID的执行完毕
    set global gtid_mode='ON'; 在Group中每个MySQL上执行
    • MySQL5.7GTID会存储到表里
      • 支持slave不用开启binlog(log_slave_status),建议还是开启
    CREATE TABLE `gtid_executed` (
      `source_uuid` char(36) NOT NULL COMMENT 'uuid of the source where the transaction was originally executed.',
      `interval_start` bigint(20) NOT NULL COMMENT 'First number of interval.',
      `interval_end` bigint(20) NOT NULL COMMENT 'Last number of interval.',
      PRIMARY KEY (`source_uuid`,`interval_start`)
    
    • 如何记录gtid

      • 如果开启binlog,在binlog日志文件切换时,将当前的gtid插入到gtid_executed表中
        • insert into mysql.gtid_executed(UUID,1000,2000);
      • 如果没有开启binlog,每个事务提交前,会执行一个insert操作
        • Begin
        • 事务操作
        • insert into mysql.gtid_executed(UUID,1000,2000); #隐式MySQL内部添加
        • commit
    • gtid_executed表压缩

      • 控制压缩频率
        • mysql>set global gtid_executed_compression_period=N;(N事务个数,默认是1000)


          压缩前后对比
    • enforce-gtid-consistency

      • OFF 不检测是否有GTID不知的语句/事务
      • WARN 当发现不支持语句/事务,返回警告,并在日志中记录警告信息
      • ON 当发现语句/事务不支持GTID时,返回错误
    • TIPS

      • 在线上从非GTID到GTID切换过程中,可以先设置成:WARN
    • GTID Limit

      • 不能使用 create table ... select ...
      • 事务中更新非事务表
        • begin:update no_trx_tabe set col1=xxx where xxx;update trx_tb set col1=xxx where ....;commit;
      • 事务中创建/删除临时表
        • begin:update trx_tb set xxx;create temporary table ...;commit;
      • sql_slave_skip_counter 不支持
      • 如果在传统复制到GTID复制切换时,主从卡住了,可以用start slave sql_thread试一下看能不能过去,要是过不去只能使用enforce-gtid-consistency=off先让主从能跑通
    • GTID跳过错误

      • stop slave sql_thread;
      • set gtid_next='uuid:N';
      • begin;commit;
      • set gtid_next='automatic';
      • start slave sql_thread;

    半同步复制

    MySQL5.7无数据丢失的半同步复制

    半同步复制
    • 半同步复制里面主从会不会存在延迟?
      • 会存在延迟,半同步只能保证写入到relay log,也就是IO_thread同步的部分,sql_thread重放有可能会出现延迟
    • 在Master接收到slave的ACK应答后才Commit事务(5.6上是Master在Commit后,才等待Slave应答)
      • 因此在事务复制到slave之前,并发的事务看不到当前的事务的数据(5.6这有点问题)
      • 当Master故障时,所有已提交的事务都会复制到slave上
      • 缺省采用无数据丢失的应答等待机制,用户可以选择使用5.6的应答待机制
      • mysql>set rpl_semi_sync_master_wait_point={AFTER_SYNC|AFTER_COMMIT}

    增强半同步

    • mysql>set rpl_semi_sync_master_wait_point=AFTER_SYNC;
      [图片上传失败...(image-e3c6a6-1513426634210)]

    半同步

    • mysql>set rpl_semi_sync_master_wait_point=AFTER_COMMIT;


      半同步

    更快的半同步复制

    • MySQL5.6


      mysql5.6半同步复制
      • mysql5.6半同步复制两个事务中间有三个流程要走,所以两个事务之间存在时间间隔
    • MySQL5.7
      • 创建单独的应答接收线程
      • 变成双工模式:发送和接收互不影响


        mysql5.7半同步复制

    5.7半同步

    • Master接收到N个Slave应答后,才Commit事务
    • 用户可以设置应答的Slave数量
    mysql>set global rpl_semi_sync_master_wait_for_slave_count=2;
    
    • 特别提示:
      • 低于5.7版本,在从库关闭一段时间后,刚启动时,注意先用异步复制,复制追上后,在用半同步复制
      • master:
        • set global rpl_semi_sync_master_enabled=ON|OFF;
      • slave:
        • set global rpl_semi_sync_slave_enabled=ON|OFF;
    • 增强半同步mysqld creash recovery
      • 扫描最后一个binlog提取其中Xid
      • 扫描InnoDB维持状态在Prepare的事务链表,和Binlog中的Xid比较,如果Binlog中存在,则提交,否则回滚事务
      • 提交到InnoDB中处于Prepare,并且写入Binlog的,就可以从崩溃中恢复事务
      • 三种场景
        • redo中有Xid,filename,position 执行Commit
        • redo中有prepare_mutex_lock,Xid
          • 在last binlog中找到对应的事务 执行Commit
          • 反之rollback
        • redo只有事务本身,没有Xid,prepare_mutex_lock 执行rollback

    并行复制

    并发复制

    • 在MySQL5.6的并发复制是基于库级别
    • 实质上需要:
      • 让在Master上能并发执行的事务,在Slave上也并发执行
      • 在Binlog中记录事务并发执行的相关信息
      • Slave上根据以上这些信息,让这些事务在Slave上多个线程中并发执行
    • MySQL5.7的并发复制是基于事务级别(Logical Clock)
    • 在Master上并发COMMIT事务越多,slave上并发性能越好
    • 微调参数
      • binlog_group_commit_sync_delay #group_commit等待时间,建议20微妙
      • binlog_group_commit_sync_no_delay_count #group_commit等待时间内到达多少个事务,比如这个参数是50个,当等待时间内已经有50个事务在等待,就直接提交,不在等待了,建议设置20
      • slave_preserve_commit_order=ON|OFF
        • 开启binlog
        • Logical_clock有作用

    基于锁的并行复制

    • 事务能不能并发是锁来决定的.如果有锁冲突,则一个事务要等待另一个事务执行完毕
    • 如何判断并行事务没有锁冲突
      • 如果两个事务(操作)可以并行执行,这两个事务没有锁的冲突
      • 当事务开始执行Commit语句时,它已经获取了所有的锁
      • 当事务进入到prepare阶段时,它已经获取了所有的锁
    • 并发信息以逻辑的时间方式写入gtid_log_event中,共记录两个逻辑时间
      • sequence_number
        • 当事务写入binlog时,事务自己的逻辑时间,按照事务记录binlog的顺序递增
      • commit_parent
        • 当事务进行prepare阶段时,已经提交的事务的最大逻辑时间
    • 事务在Slave上执行
    动作 事务 依赖关系
    insert commit T1 (1,0)
    update commit T2 (2,0)
    delete commit T3 (3,1)
    • commit_parent之前执行的事务全部提交以后,才开始执行
    • T1和T2同事开始执行,T1 Commit后,T3开始执行

    启用并行复制

    • 启用GTID!!!
    mysql>stop slave sql_thread;
    mysql>set global slave_parallel_workers=4|8|max_cpu_core/2;  #最多可以设成cpu核数,不过不建议,一般4个或8个就够了
    mysql>set global slave_parallel_type='LOGICAL_CLOCK'; #OR DATABASE
    mysql>start slave sql_thread;
    
    
    • MySQL 5.7并行复制的思想简单易懂,一言以蔽之: 一个组提交的事务都是可以并行回放 ,因为这些事务都已进入到事务的prepare阶段,则说明事务之间没有任何冲突(否则就不可能提交)。
    • DATABASE:默认值,基于库的并行复制方式
    • LOGICAL_CLOCK:基于组提交的并行复制方式
    • 最好配置binlog group commit
      • binlog_group_commit_sync_delay
      • binlog_group_commit_sync_no_delay_count

    延迟复制

    • 让从库和主库保持固定时间的延迟
    • 使用场景
      • 利用延迟复制做误操作恢复
      • 利用延迟复制做统计分析环境处理
    mysql>stop slave sql_thread;
    mysql>change master to master_delay=N;  #N单位秒
    mysql>start slave sql_thread;
    
    • 从库在某一个复制位置停住
      • start slave中有个参数为until可以实现这个功能
      • start slave sql_thread until master_log_file='xxx',master_log_pos=xxx;
      • 或者可以用GTID模式,{SQL_BEFORE_GTIDS|SQL_AFTER_GTIDS}=gtid_set

    多源复制

    • Slave 可以同时从多个Master复制
    • 每个DB中的名字不能一样,否则有可能复制出错
      [图片上传失败...(image-6f90e6-1513426634210)]
    • 场景
      • 集中备份
      • 数据分析聚合
      • 分片数据聚合


    • 多个channels(channels包含:recevier thread ,relay logs ,applier threads)每个channel能独立的运行和停止
    • 通过P_S表进行状态监控:
    • 下列表中添加了channel_name字段,不同的Channel的信息在不同的行中显示
      • replication_applier_status_by_coordinator
      • replication_applier_status_by_worker
      • replication_connection_status

    group replication

    group replication
    • Group Replication的实质是:
      • 二进制日志
      • 基于Row格式+GTID
      • 一个通信框架+事务排序控制(atomic message delivery & total ordering of message)
      • 增强半同步 & 并行复制
    • Group Replication是一个趋势
    • 备份不好搞定
      • mysqldump不支持一致性备份(5.7.18后支持)
      • xtrabackup备份,造成性能损失比较严重
    • 新的节点加入过程对原有集群性能有影响

    5.7复制其他方面的增强

    • 动态变更filter
      • 不需要重启MySQL
      • 支持所有的Filter选项
      • 支持各种字符集
    mysql>stop slave sql_thread;
    mysql>CHANGE REPLICATION FILTER REPLICATE_DO_DB= (db1,db2);
    mysql>start slave sql_thread;
    
    • 切换主时不用停sql_tread
    • 切换master时,只需停止io_thread,不需要停止sql_thread
    mysql>stop slave io_thread;
    mysql>change master to master_host='master-2',...;
    mysql>start slave io_thread;
    
    • Replication的信息添加到了Performance Schema中
      • 通过SQL进行监控
      • 逻辑上无关的信息被放在不同的表中
    • 配置信息表
      • replication_connection_configuration
      • replication_applier_configuration
    • 状态信息表
      • replication_connection_status
      • replication_applier_status
      • replication_applier_status_by_coordinator
      • replication_applier_status_by_worker

    相关文章

      网友评论

          本文标题:剖析复制线程

          本文链接:https://www.haomeiwen.com/subject/vlhdwxtx.html