MySQL复制相关(持续更新)

一、异步复制

异步复制原理图

after commit
  • master:
    • Dump_Thread,通知IO_Thread数据变更
  • slave:
    • IO_Thread,拉取binlog增量
    • SQL_Thread,SQL逻辑重放

异步复制流程

  1. master 写undo、redo
  2. master 发起commit,写binlog(filename,position)
  3. master 完成提交事务
  4. slave 通过IO_Thread拉取binlog的filename,position,并写入到本地的relaylog中
  5. slave 通过SQL_Thread逻辑重放relaylog中的SQL(单线程)

两种场景

  1. 实时同步(IO_Thread主从没有延迟),写数据之前通知IO_Thread有变更,IO_Thread拉取binlog增量
  2. 主从长时间延迟(全备恢复),IO_Thread直接去主库本地磁盘拉取binlog增量

复制中的坑

  1. row模式下,表最好是有主键,其次要有普通索引。否则sql_thread重放需要全表扫描匹配,速度非常慢(mysql5.7中做了优化)


    sql_thread重放

二、半同步复制(MySQL 5.5 after commit)

半同步复制流程图

after commit

半同步复制流程

  1. master 写undo、redo
  2. master 发起commit,sync binlog(filename,position)
  3. master 存储引擎commit完成
  4. master_sender_thread 等待slave_reciver_thread返回ack(等待过程中会阻塞下一个事务)
  5. master_sender_thread接收到slave_reciver_thread返回的ack,并返回给客户端,客户端才可以继续操作

after带来的三个问题

  1. 性能问题:AFTER_COMMIT半同步是单线程处理的,master把事务发送完毕后,要接受和处理slave的ack应答,处理完ack后才能继续发送下一个事务,对性能影响比较大
  2. master commit完成后才开始等待slave的ACK,其实这个时候在master上事务已经提交完成并且其他客户端已经可以读到,只是提交该事物的客户端处于等待状态。
  3. 如果master等待ack时master crash,而slave又未接收到该事务的话,那么切换到从库后就会出现读取的结果不一致的情况(因为主库已commit而从库未收到该事务binlog)

三、增强半同步复制(MySQL 5.7 after sync)

增强半同步复制流程图

after sync

增强半同步复制流程

  1. master 写undo、redo
  2. master 发起commit,sync binlog(filename,position)
  3. master 通过单独的semisync_reciver_thread等待slave_reciver_thread返回ack,此过程中master_sender_thread可以处理其他事务的请求
  4. semisync_reciver_thread接收到slave_reciver_thread返回的ack,并返回给客户端
  5. master 存储引擎层commit

增强半同步解决的问题

  1. AFTER_SYNC采用双工处理,master采用单独semisync_reciver_thread处理ack应答,不阻塞其他事务,提升性能
  2. AFTER_SYNC等待ack的操作是在引擎层commit之前处理,避免了其他客户端脏读
  3. 在等待ack的期间master crash,由于master引擎层未commit,如果slave未接受到该事务,那么数据是一致的

增强半同步带来的新问题

极端情况:在master sync binlog(写入xid)后,且在发送日志之前,这个时间master crash了。那么slave是没有拿到master的binlog增量的,而master重启后的crash recovery会认为该事务已写到binlog中,然后进行重做。这样就会导致主从不一致

5.7增强半同步配置

  1. master
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
set global rpl_semi_sync_master_enabled=ON;
  1. slave
 install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
  set global rpl_semi_sync_slave_enabled=ON;
  1. 主要参数
  • mster:
    • rpl_semi_sync_master_enabled=ON 表示在master上已经开启半同步复制模式。
    • rpl_semi_sync_master_timeout=10000 该参数默认为10000毫秒,即10秒,可以调整,表示如果主库在某次事务中等待事件超过10秒,则降级为异步复制模式,不再等待slave,如果master探测到slave恢复,则会自动回到半同步模式。
    • rpl_semi_sync_master_wait_no_slave=ON 表示是否允许master每个事务提交后都要等待slave的确认信号,默认是ON,即每一个事务都会等待,如果是OFF,则slave追赶上之后,也不会回到半同步模式。
    • rpl_semi_sync_master_trace_level=32 表示开启半同步复制模式时的调试级别,默认是32
  • slave:
    • rpl_semi_sync_slave_enabled=ON
    • rpl_semi_sync_master_trace_level=32

四、并行复制

并行复制的演变

  • MySQL 5.6 是基于库级别的并行复制(适用于单实例多库而且库之间的写入分布比较平均的情况,比较鸡肋,可以忽略)
  • MySQL 5.7 是基于事务级别的并行复制(主要介绍)
  • MySQL 8.0 是基于行级别的并行复制(太新还没来得及研究,后面补上)

MySQL 5.7基于行的并行复制

原理:
与组提交结合,一个组提交的事务都是可以并行回放,因为这些事务都已进入到事务的prepare阶段,则说明事务之间没有任何冲突(否则就不可能提交)。

复制中的重要参数

  • log-bin = /binlog_dir
  • binlog_format = row
  • binlog_row_image = full //默认full
  • gtid_mode = on
  • enforce_gtid_consistency = on //打开gtid之前必须打开此选项,服务器通过允许仅执行可使用GTID安全记录的语句来强制执行GTID一致性(开启后强制检测gtid一致性,在事务中更改非事务表将会报错)
  • binlog_group_commit_sync_delay = 100 //单位(微秒)。如果不启用组提交,则每次提交一个事务,binlog做一次fsync。如果启用了binlog-group-commit,此时sync_binlog=N代表每N组事务,而不是每N个事务。建议设置sync_binlog=1
  • binlog_group_commit_sync_no_delay_count = 10
  • binlog_order_commit = off //开启后事务提交顺序与binlog顺序一致,默认on,设置为off则事务可并行提交,对数据一致性可能产生影响。如果启用了binlog-group-commit,则设置为off
  • transaction_write_set_extraction = on //8.0特性,5.7默认off
  • binlog_transation_dependency_tracking = COMMIT_ORDER //等同于打开binlog_order_commit,基于行级别并行复制配置成writeset_session
  • binlog_transation_dependency_history_size = 25000 //控制队列长度
  • slave_net_timeout = 20|30 //io_thread超时时间
  • log_slave_updates
  • slave_parallel_type = LOGICAL_CLOCK //从库开启并行复制
  • slave_parallel_type = 4|8
  • slave_preserve_commit_order = on //保证从库提交顺序与主库一致,前置条件log-bin,log_slave_update,slave_parallel_type = LOGICAL_CLOCK
  • slave_rows_search_algorithms = TABLE_SCAN,INDEX_SCAN //配置成INDEX_SCAN,HASH_SCAN,当没主键的表复制中可以用hash索引
  • relay_log_info_reposity = table //crash-safe replication
  • sync_relay_log_info = 1
  • relay_log_recovery = 1

你可能感兴趣的:(MySQL复制相关(持续更新))