MySQL replication 演进
MySQL 5.5 半同步的复制
简介
主库在执行完客户端提交的事务之后不立即返回,等待至少一个从库接收并且写入到relay log中才返回客户端,提高了数据的安全性,但是造成了一定程度的延迟,降低了数据库的性能
其他同步概念
异步复制:MySQL默认复制方式,主库在执行完操作后立即返回,而不关心从库是否已经接受、处理,可能造成数据不一致
全同步复制:主库执行完一个事务必须要等其他从库都同步完成后才返回,性能严重受损
MySQL 5.6 并行复制
简介
针对 数据库中存在多个schema,并且schema下表的数量较少,开启并行复制对速度有较大的帮助
开启后SQL线程变成coordinator线程,负责如下功能:
1.判断可以并行执行,选择worker线程执行事务的二进制操作
2.判断不可执行,例如操作是DDL,或者事务是跨schema操作的,等待所有的worker执行完成之后再执行当前日志
存在问题
若实例中有很少的库和较多的表,回放的效果会很差,性能甚至会比单线程较差,而单库多表是常见的情况
MySQL 5.7 组提交
简介
数据库为了保障数据的安全性,往往采用了WAL机制(Write-Ahead-Log)
1.在对数据修改之前,必须先将为修改记录日志,保证了事务的ACID机制
2.Redo log就是WAL的一种应用,当数据库突然掉电再重新启动时,可以通过Redo log来还原数据,每次事务提交时则不需要同步刷新数据文件,只需要追加Redo log就足够了
为了保障redo log和 binlog日志的数据一致性,MySQL使用了两阶段提交:
1.prepare阶段:redo日志持久化到磁盘,并将回滚段设置为prepared状态,binlog不做任何操作
2.commit阶段:innodb释放锁,释放回滚段,binlog持久花园到磁盘,然后在innodb提交
由binlog作为事务的协调者,根据redo日志是否落盘来判断在故障发生时是重做还是回滚:
1.异常发生后,实例重启时,如果binlog已经落盘,则提交
2.若binlog未落盘,则事务回滚
同时为binlog增加组提交的方式,分为了三个阶段((Flush 阶段、Sync 阶段、Commit 阶段),转换为批处理操作,提高性能
流程
在MySQL中的每一个阶段都有一个队列,每一个队列都有一把锁保护,第一个进入队列的事务会成为Leader,由Leader领导所在队列中的事务,完成后通知队列内其他事务操作结束
Flush阶段
1.获取队列中的事务组,将Redo log在prepare阶段落盘
2.将binlog写入到文件,此时只是写入文件系统的缓存中,不保证崩溃binlog不丢失,重启后可能会回滚该组事务
3.Flush阶段的作用是提供了redo Log的组提交
Sync阶段
1.增加一组事务中的事务的数量,提高落盘的收益,由两个指标控制落盘的时机
2.binlog_group_commit_sync_delay=N 延迟N μs后,开始事务刷盘
3.binlog_group_commit_sync_no_delay_count=N,队列中的事务达到N个,立即刷盘
4.在这一阶段崩溃后,事务会通过Flush阶段的redo 日志重做,因为Binlog已经落盘了,
5.Sync阶段是为了支持binlog提交
Commit阶段
1.获取队列中的事务组
2.将Redo log中已经prepare的事务在存储引擎层提交—commit
.3.Commit阶段队列的作用是承接Sync阶段的事务,完成最后的引擎提交,使得Sync可以尽早的处理下一组事务,提高效率
注意
Group Commit虽然是属于并行提交的技术,但是却意外解决了从服务器上事务并行回放的一个难题——即如何判断哪些事务可以并行回放。
为了标记事务所属的组,MySQL5.7版本在产生Binlog日志时会有两个特殊的值记录在 Binlog Event 中,
1.last_committed: 该事务提交时,上一个事务提交的编号
2.sequence_number:事务提交的序列号,在一个Binlog文件内单调递增
如果两个事务的last_committed值一致,这两个事务就是在一个组内提交的。
存在问题
1.在主服务器上并行提交事务才能在从服务器上并行回放
组复制模式
简介
至少由3个节点共同组成一个数据库集群,事务的提交必须经过半数以上的节点同意后方可提交,在集群中每个节点上都维护一个数据库状态机,保证节点间事务的一致性。
基于Paxos分布式一致性算法,只要超过半数以上的节点存货就不会对数据库服务造成影响,支持两种模式:
1.单主模式:只有一个节点可以对外提供读写事务,其他节点提供只读服务
2.多主模式:多个节点提供对外的读写事务服务,节点间事务可能有比较大的冲突,影响性能,限制了查询语句
在MGR集群中,回访的时候可以通过并行的方式回放,使用WriteSet技术检测冲突
相较于之前的复制方案,它新增了certify模块,用于检测事务是否允许提交,是否和其他事务存在冲突,使用乐观锁来对待事务之间的冲突,执行的过程如下:
1.节点s1发起一个更新事务T1,同时节点s2发起更新事务T2,T1在s1本地执行完成后,将其WriteSet和版本dbv=1发送给group,T2同样如此。
2.xcom通讯协议保证了消息的有序传送,假设先收到T1事务的请求,发现当前版本cv=1,数据更新版本dbv=1,没有冲突,完成提交cv=2
3.之后又收到了T2事务的certify请求,dbv=1,而当前的cv=1拒接,事务T2回滚
事务依赖关系
在MySQL8.0中提供了三种用于事务的依赖关系:
1.COMMIT_ORDERE:表示继续使用5.7中的基于组提交的方式决定事务的依赖关系(默认值);
2.WRITESET:表示使用写集合来决定事务的依赖关系;
3.WRITESET_SESSION:表示使用WriteSet来决定事务的依赖关系,但是同一个Session内的事务不会有相同的last_committed值。
MySQL采用一个vector的变量存储已经提交的事务的HASH值,所有已经提交的事务的所修改的主键和非空的UniqueKey的值经过HASH后与该vector中的值对比,由此来判断当前提交的事务是否与已经提交的事务更新了同一行,并以此确定依赖关系。
WriteSet依赖检测
MySQL会有一个变量来存储已经提交的事务HASH值,所有已经提交的事务所修改的主键(或唯一键)的值经过hash后都会与那个变量的集合进行对比,来判断改行是否与其冲突,并以此来确定依赖关系
作者:Tommenx
原文链接:https://blog.csdn.net/Tommenx/article/details/105934976