当前位置: 移动技术网 > IT编程>数据库>Mysql > 漫谈MySQL复制技术

漫谈MySQL复制技术

2020年07月21日  | 移动技术网IT编程  | 我要评论

一、异步复制

MySQL默认的复制方式,master将事务写入binlog后直接返回客户端事务执行成功并commit,事务线程不需要等待binlog是否有传输至slave并应用完毕。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CIETVZnh-1595144608475)(http://note.youdao.com/yws/res/54162/F2D5A080332C487B9295B748499D58DF)]

1.1 基本原理

异步复制的基本流程:

    1)master将事务写入binlog并通知dump线程发送这些binlog event至slave
    2)master事务线程提交事务并返回客户端事务commit成功
    3)slave的IO线程异步处理master传输过来的binlog日志并写入relaylog
    4)slave的SQL线程应用relaylog追上同步

1.2 潜在风险

master不关注slave是否接收到事务日志,若因为某些原因slave没有接收到这部分的binlog日志,此时master宕机,HA将主库切至slave作为new master,那么此时的new master数据丢失。

二、半同步复制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S6NCUsT2-1595144608480)(http://note.youdao.com/yws/res/54164/F429CFAFBB0B4596894B79DBC990289A)]

半同步复制其实是在异步复制的基础上增加了一个ack的操作。master将事务的event写入binlog后,事务线程必须等待slave的ack后才可以进行下一步操作,否则事务线程处于阻塞等待状态,直到超过一定时间限制,MySQL主动将半同步复制降级为异步复制。

2.1 after commit

1、基本原理

after commit是MySQL 5.6默认的半同步模式。

after commit下半同步复制处理流程:

    1)master将事务写入binlog并通知dump线程发送这些binlog event到slave
    2)master提交事务并等待slave的ack
    3)slave的IO线程接收到master的事务日志并写入到relay log,向master返回ack
    4)master接收到slave的ack后,返回客户端commit成功
    5)slave的SQL线程应用relaylog追上同步

2、潜在风险点

该模式下,在master还没有接收到slave的ack之前就已经将事务提交,然后再等到salve的ack后返回客户端commit成功。
该事务在master的引擎层已经提交,此时master的该事务对于其他事务已经可见,但slave还没有读到该事务。如果在等待slave的ack时,master宕机了,slave并没有将该事务写入relay log中,此时的slave是丢数据的。

2.2 after sync

after sync模式是MySQL5.7后新增,并且为MySQL5.7半同步复制的默认模式。

1、基本原理

    1)master将事务写入binlog并通知dump线程发送这些binlog event到slave
    2)master的ack collector线程等待slave的ack
        MySQL5.7 之前,dump线程同时承担传递binlog和接收ack的工作,且两个工作是串行的
        MySQL5.7 之后,新增一个ack collector线程专门用于等到slave的ack,不影响dump线程继续处理下一个事务,一定程度上提高的并发处理事务的能力
    3)slave的IO线程接收到事务日志并写入relaylog后,slave向master返回ack
    4)master接收到ack后,提交事务并返回客户端commit成功
        MySQL5.7 之后,在一主多从的架构中可控制master接收ack的数量
    5)slave的SQL线程应用relaylog追上复制

2、潜在风险点

所有客户端看到的数据都是,slave已ack完成,master已commit到存储引擎后的数据。

在该模式下,保证数据不丢失。若master在等待slave的ack前挂了,对应的binlog已经做了sync操作,slave已经收到了这些binlog,并且应用成功,此时slave上相对于master是多了数据的。

2.3 半同步复制相关参数理解

以下半同步复制参数必须在安装半同步插件以及打开半同步复制后,才可显示。

1、master相关

    rpl_semi_sync_master_enabled:
        控制master端是否打开半同步插件,默认OFF 
        
    rpl_semi_sync_master_timeout:
        控制半同步复制退化为异步复制的时间限制。
        若该时间限制下master还未接收到slave的ack,半同步复制退化为异步复制。默认10000(10s)
        该参数一般会设置比较大,保证数据无损。
        
    rpl_semi_sync_master_trace_level:
        master半同步复制调试跟踪等级,默认为32。
        1 = general level (for example, time function failures)
        16 = detail level (more verbose information)
        32 = net wait level (more information about network waits)
        64 = function level (information about function entry and exit)
        
    rpl_semi_sync_master_wait_for_slave_count:
        master提交事务并返回客户端commit时,需要获取slave的ack的个数,默认为1。该参数同样依赖rpl_semi_sync_master_wait_no_slave的设置。
        
    rpl_semi_sync_master_wait_no_slave:
        控制当slave个数小于rpl_semi_sync_master_wait_for_slave_count参数设置时,复制模式的行为,默认为ON。
        ON:当MySQL发现slave个数小于rpl_semi_sync_master_wait_for_slave_count时,MySQL复制模式不做任何变更,只要数据同步时,master接收到大于等于rpl_semi_sync_master_wait_for_slave_count个数的ack,MySQL就继续保持半同步复制模式;
        若master等待ack超过rpl_semi_sync_master_timeout时间限制后仍然未接收到大于等于rpl_semi_sync_master_wait_for_slave_count个数的ack,MySQL就将半同步复制退化为异步复制。 
        OFF:当MySQL发现slave个数小于rpl_semi_sync_master_wait_for_slave_count时,主动将半同步复制退化为异步复制

    rpl_semi_sync_master_wait_point:
        控制半同步复制下,master提交事务并返回客户端commit的时机,MySQL5.7版本下默认为after_sync。

2、slave相关

    rpl_semi_sync_slave_enabled:
        控制slave端是否开启半同步复制,默认为OFF
    rpl_semi_sync_slave_trace_level:
        控制slave半同步复制调试跟踪等级,默认为32。

2.4 如何开启半同步复制

1、master端

##安装半同步复制插件
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';

##打开半同步复制功能
mysql> set global rpl_semi_sync_master_enabled=ON;

##检查半同步复制相关参数设置
mysql> show variables like  '%semi%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 10000      |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.01 sec)

2、slave端

##安装半同步复制插件
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';

##打开slave端的半同步复制功能
mysql> set global rpl_semi_sync_slave_enabled=on;
Query OK, 0 rows affected (0.00 sec)

##检查半同步复制相关参数
mysql> show variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_slave_enabled               | ON         |
| rpl_semi_sync_slave_trace_level           | 32         |
+-------------------------------------------+------------+
2 rows in set (0.00 sec)

##开启slave复制线程并检查复制状态
mysql> start slave;
mysql> show slave status\G

三、组复制

组复制是MySQL5.7.17开始官方开发的一个开源插件,是实现MySQL高可用集群的一个工具。组复制主要基于一个组的概念,所有被组复制插件连接在一起的MySQL服务器组成一个高可用集群组。该高可用组内所有的成员的管理、复制、高可用failover都通过group replication插件进行管理控制。

基于组复制的概念大可分为两种高可用架构模型:单主模型、多主模型。单主模型只有一个主节点可以接受写操作,主节点故障时可以自动选举主节点。多主模型下,所有节点都可以接受写操作,没有master-slave的概念。

3.1 基本原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AilQVetu-1595144608491)(http://note.youdao.com/yws/res/54030/F00629EC15D348BC8B50ECFAB625B513)]

本地事务控制模块、成员间的通信模块、全局事务认证模块、异地事务执行模块

##ececute
1)本地事务控制模块将事务执行的相关信息进行打包,每个事务打包成一个数据包
    主键信息:库名、表名、主键值等信息产生的hash值
    数据库快照版本:gtid_executed
    事务相关信息:binlog event
##consensus
2)通信模块将这些数据包拉取到本地数据队列等待后续处理(本地事务)、并同步本地数据队列的数据包到其他成员上等待后续处理(异地事务)
3)通信模块通过满足paxos协议,保证大多数成员接收到该事务信息后,再把该数据包发送给全局事务认证模块;为保证数据包发送给全局事务认证模块的顺序于通信模块接收的顺序一致,paxos协议会为每个同步成功的数据包分配唯一的ID号并顺序排序。
##certify
4)全局事务认证模块通过数据包信息进行冲突性检测
    以数据行为单位进行冲突性检测
##冲突性检测后的处理主要分为本地事务和异地事务两种情况
6)对于本地事务:若检测没有冲突,唤醒本地事务控制模块的事务线程进行提交操作;若检测有冲突,唤醒本地事务控制模块的事务线程进行回滚;以上操作完成后丢弃binlog event
7)对于异地事务:若检测没有冲突,通过全局事务认证模块的api将该事务的binlog event写入到relaylog中,并通过group_replication_applier进行应用;若检测有冲突,则丢弃该事务的binlog event
    

3.2 特点

1)组复制中不会出现脑裂的现象

2)基于Paxos协议,保证binlog event至少被复制到大多数成员上,只要同时宕机成员不超过半数就不会导致数据丢失

3)组复制保证只要BInlog event没有传输到半数以上的成员,本地成员不会将事务的binlog event写入到binlog文件和提交事务,从而保证宕机的服务器上不会有组内在线成员上不存在的数据。

3.3 组复制相关参数

    transaction_write_set_extraction:
        指定事务记录write set使用的算法,默认OFF,若需要打开组复制需要将该参数设置为XXHASH64
    
    binlog_transaction_dependency_tracking:
        控制master端各个事务的last_committed和sequence_number记录准则,实现slave库的并发多线程复制
        COMMIT_ORDER:基于组提交方式进行多线程并发
        WRITESET:基于write set方式进行多线程并发,该模式下同一个session的多个事务在同一分组下可并发复制
        WRITESET_SESSION:基于write set方式进行多线程并发,该模式下同一个session的多个事务在同一分组下不可并发

    binlog_transaction_dependency_history_size:
        记录事务的hash值的上线,默认25000,若超过该参数值则开始清理历史记录

四、多线程并行复制的发展

4.1 基于MySQL 5.6的并行复制

在MySQL5.6版本中,多线程并行复制是基于库级别的并行复制。也就是说只有在实例中涉及多个schema,且每个shcema数据写入比较均匀的情况下,该并行复制才可以发挥一定的价值。但是实际业务场景中一般都是单实例当schema,所以MySQL5.6版本的并行复制并没有很好的利用并行复制减轻slave复制延迟的问题。

4.2 基于MySQL 5.7的并行复制

在MySQL5.7版本中,在兼容5.6的库级别并行复制的基础上增加了基于逻辑时钟(logical clock)的并行复制。该并行复制模式下,所有已经处于prepare状态的事务都是可以并行提交(组提交),同样slave也可以并行回放这些事务。处于prepare阶段的这些事务都是无冲突的,若存在冲突,后提交的事务无法进入prepare阶段,一直等待资源直到该资源被释放。

MySQL并行复制模式通过slave_parallel_type进行控制,database表示5.6版本基于schema的并行复制;logical_clock表示基于组提交进行并行复制。

1、Group Commit 如何进行分组?

1)gtid

在MySQL5.7中,我们可以从binlog日志中通过gtid的信息查看MySQL具体是如何进行组提交执行各个事务的。主要关注last_committed和sequence_number。

每个binlog日志的gtid分组序列信息都会清零重新开始计算:

last_committed从0开始计数,sequence_number从1开始计数;
新的一组的last_committed=sequence_number-1;
新的一组的last_committed=上一分组的sequence_number。

相同的last_committed为一组,sequence_number标志组提交中事务提交的顺序。

对于没有开启gtid的情况,binlog日志中以Anonymous_Gtid记录。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X43Dw2sw-1595144608497)(http://note.youdao.com/yws/res/53825/E8C7F719335E49FC97EBA0B5CE4D93F4)]

2)order commit

gtid可以看到MySQL组提交的实现的表现,当内部具体是如何实现这些事务分组还需要了解MySQL中order commit的概念。

事务提交主要分为三个阶段:flush、sync、commit:

  • flush(flushing transactions to binary log)

该阶段主要工作是,将该队列中Redo log中prepare阶段的数据刷盘,实现了redo 的组提交(将redo log中 prepare阶段的日志进行刷盘),并将binlog日志写入文件系统的缓冲,通知dump线程dump binlog (不能保证数据库崩溃时binlog不丢失)。

flush阶段实现了redo的组提交(5.7.6之后实现,之前都是每个事务提交必须进行一次redo刷盘)

一个新的事务提交,查看当前flush队列是否空闲,若flush队列正在被占用且超过该组提交的时限则等待队列资源;

当flush队列空闲时,第一个进入队列的事务作为组提交的队长,通知dump线程进行复制;

为所有加入该组的事务都分配一个last_committed和sequence_number。如果是该分组的第一个事务则sequence_number加1计数,last_committed为上一分组的sequence_number;

将每个事务的last_committed、sequence_number,以及具体的event事件依次flush到binlog日志;(保证所有顺序都是提交加入到队列的顺序)

  • sync(Syncing binary log file to disk)

该阶段的主要工作是实现binlog的组提交,对binlog日志进行刷盘(MySQL重启后通过Flush 阶段中Redo log刷盘的数据继续进行事务的提交)

一个分组的所有事务flush到binlog日志后,队长去判断sync队列是否空闲,若sync队列被占用则等待;

若sync队列空闲,该分组下所有事务依次做sync操作;

MySQL使用两个参数控制获取队列事务组的时机:

binlog_group_commit_sync_delay=N:在等待N μs后,开始事务刷盘
binlog_group_commit_sync_no_delay_count=N:如果队列中的事务数达到N个,就忽视binlog_group_commit_sync_delay的设置,直接开始刷盘
  • commit(Commit all transactions in order)

该阶段的主要工作是依次将Redo log中已经prepare的事务在引擎层提交,commit阶段不存在刷盘的操作,flush阶段中的Redo log刷盘已经足够保证数据库崩溃时的数据安全了

当分组中所有事务都完成sync操作后,开始进行commit操作,commit行为会受到binlog_order_commits参数的影响;

若binlog_order_commits为ON,则表示该分组内所有事务通过单线程按照写入binlog的顺序进行串行化commit;

若binlog_order_commits为OFF,则表示该分组内所有事务不考虑写入binlog日志的顺序,可以通过多线程并发提交。另外保证来自同一个客户端的事务是按时间顺序进行提交。(若希望从库与主库的事务提交顺序一致需要在从库设置slave_preserve_commit_order=1 )

2、logical clock特点

1)通过order commmit通过gtid序列号实现事务的分组

2)该模式下只有主库并发比较大的情况下,才会发生每个分组中多个事务的情况,才能实现logical clock多线程并行复制的优势

3、从库的并行回放策略

slave是以事务为单位进行应用的,以下是slave多线程复制并行回放的主要流程:

1)slave的SQL线程获取到一个新的事务,先取出该事务的last_committed和sequence_number

2)判断该事务的last_committed是否大于当前正在应用的事务的sequence_number

3)若该断事务的last_committed大于当前正在应用的事务的sequence_number,则表示上一个分组还在应用中,继续等待

4)若该事务的last_committed小于或等于当前正在应用的事务的sequence_number,则表示该事务与当前正在应用的事务属于同一分组,可并行回放

5)SQL线程找到一个空闲的work线程,由该work线程应用该事务;若当前没有空闲的work线程则继续等待work线程的资源被释放

4、基于组提交的并行复制相关参数

slave-parallel-type=LOGICAL_CLOCK       //基于LOGICAL_CLOCK进行并行复制
slave-parallel-workers=16               //并发复制线程数
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON

4.3 基于write set的并行复制

基于组提交的并行复制的优势只有在master并发压力比较大的时候才可以体现出来,为进一步提高MySQL并行复制的能力,MySQL8.0(5.7.22后也可使用)同样使用logical clock进行多线程并发复制,但是推出了新的判断是否可并行回放的策略,通过检测事务在运行过程中是否存在写冲突来决定slave上的回放顺序,这使得slave的并发程度不再依赖于master。该技术主要应用在MGR中。

1、write set 的冲突性检测

主要通过该事务的主键hash/快照版本,以及内存中维护的 【主键hash+该主键最后一次修改的快照版本】 列表进行比对。若该事务的快照版本包含列表中所有主键的快照版本,则表示不冲突可并发执行;否则就表示有冲突进行回滚。

2、基于writeset的并行复制相关参数

# master
transaction_write_set_extraction = XXHASH64             //对主键信息进行hash计算
binlog_transaction_dependency_tracking = WRITESET   //多线程并发方式
binlog_transaction_dependency_history_size = 25000  //内存中存储主键hash+快照版本信息最大记录数

#slave
slave-parallel-type = LOGICAL_CLOCK     //开启基于逻辑时间的并行复制
slave-parallel-workers = 8              //并发线程数

相关文档:

  • https://mp.weixin.qq.com/s/7aAKJCTZXqE1xv0Jgtl6Cw
  • https://yq.aliyun.com/articles/617776
  • https://www.cnblogs.com/cchust/p/4439107.html

本文地址:https://blog.csdn.net/weixin_37692493/article/details/107446265

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网