12月8-9日,由中国计算机行业协会开源数据库专业委员会与中国MySQL 用户组联合举办的为期两天的"2018 ACMUG 全球年会盛典"技术分享会议。我们生产运营部系统管理中心徐春阳受邀参加了此次分享活动,并以“MySQL Group Replication 基础与实践”为主题,深度介绍了MySQL Group Replication(下面简称MGR)这两方面的内容,并从运维人员的角度,分享对MGR的思考。

以下是我们中心徐春阳在大会上分享的内容:

大家下午好, 这个是今天我分享的题目------“MySQL Group Replication基础与实践”。在讲之前,我先简单地做一下自我介绍:我来自于民生银行总行信息科技部,之前在国内的大型互联网公司工作,来到民生银行之后,依然是从事数据库运维工作,主要精力集中在开源数据库MySQL上面。大家可能有这样的观点:开源数据库MySQL在传统银行业应该是比较边缘的数据库产品,不会是银行业的主流或者核心的数据库。不知道大家之前有没有从其它渠道了解到民生银行今年上线了一个系统,它是国内传统银行业内第一个上线的分布式核心系统,其背后运行的数据库就是MySQL数据库。如再加一个第一的话,我觉得,应该也可以说是传统银行业内在核心系统上使用的第一个MySQL数据库。该系统已经于今年的1月28日正式上线,上线至今已经接近一年,运行相当稳定。

这个是我们今天要讲的内容。首先会介绍一下MGR的原理,然后会将其与MySQL的semi-sync来进行比较,最后一部份会介绍MGR的实践。希望今天的分享,能给大家在认识MGR或者使用MGR过程中提供一点参考或者帮助。

我们来看一下MGR的主要特点:

MGR的第一个特点就是支持多节点并发地执行事务。我们知道MGR是多节点多副本的集群,有多少个节点,数据就有多少份。节点之间的数据是最终完全一致的。所以,要支持从多个节点并发执行事务,就必需考虑到如何保证从各个节点并发执行的事务在每个节点都以相同的顺序被执行/应用,这样节点之间的数据才能最终一致。 这个是Paxos协议的功能。

另外一个特征,就是自动地事务冲突检测。 假如有两个事物:事务A跟事务B,它们更新同一条记录,而且也同时执行。 假如说,这两个事务在同一个节点内执行,通过数据库实例内部的锁机制就能解决这个冲突,让先获得锁的事务先执行。但是,在MGR中,如果这两个事务同时从不同的节点执行------事务A在A节点执行,事务B在B节点执行,同样这两个事务也是更新同一条记录。在事务的执行阶段,这两个事务是完全独立的,是相互不可见的,是完全感知不到对方的存在。只有当事务执行到binlog提交的阶段,将事务的日志通过paxos协议广播到对方节点之后,它们才能感知到对方的存在。然后利用这些日志,就能验证事务A跟事务B是否有冲突。  这就是冲突检查的机制, 后面还会继续讲到该部分的内容。

另外就是节点故障容忍度强,这个是paxos协议的多数派原则,当单个节点故障,不影响集群整体可用性,只要没有超过半数的节点宕机就可以。但为什么在这里打了个疑问号,讲完之后大家可能就知道。

最后一个特点,就是更高级别地保证数据一致性。大家可能都知道,如果我们使用MySQL主从做高可用方案,需要避免这些情况的发生:

第一种:新主库激活得太早,新主库还没有将老主库发送过来的日志应用完,新主库就接管流量。新主库在有延迟的数据版本上接管了流量,这个是不允许的。

第二种:新主库跟老主库双活,并都有流量写入,这就是通常所说的“脑裂”,切换程序以为老主库宕掉了,但实际上没宕机,两边都有业务流量,数据的一致性将严重破坏。

第三种:就是数据丢失。主库服务器在宕机之前,没有将所有的日志发送给从库。此时启用从库作主库,数据将丢失。

对于这些问题,从理论上来讲,MGR可以完美解决。MGR本身就是为了解决这些问题而出现的。

刚才我们讲了MGR的功能,这些功能是由两个底层基础模块来实现的:1,Paxos协议的实现模块。2,冲突检查功能模块。我们先看看paxos协议。

Paxos协议的实现细节还是相当复杂的,我们作为运维人员,可能不需要了解到非常具体的细节,但我们需要了解它实现的功能,以便我们能更好地理解MGR。首先,它实现并发消息的全局排序, 简单来说,就是将从各个节点并发执行的事务进行统一地排序,保证每个节点执行的事务是相同的,顺序也是一致的。另外,就是需要处理一些异常,假如某个消息,已经发给了某个节点,但还有大多数的节点没有收到这个消息,则已经收到这个消息的节点就要把这个消息丢掉。另外,就是多数派原则,刚才已经讲过。特别说明一下,Paxos协议本身不处理冲突,它不关心消息里面所包含的内容具体是什么,只负责对并发消息进行全局排序并一致性广播,处理冲突在应用消息或者说执行消息的过程中发生的。下面我们就来讲冲突检测的内容。

冲突检查的原理是,将事务所涉及的主键去写集合(write set)里面查找,如果命中,则比较它们各自事务所基于的数据版本,数据版本用gtid set来表示,通过比较事务执行时所基于的数据版本,来判定事务间执行的先后顺序是否正确。如果是包含关系,则不冲突。因为这两个事务,虽然更新了同一条记录,但它们是正常的先后顺序。如果是等于或者被包含关系,则冲突。等于关系呢,就表示这两个事务基于相同的数据版本,从不同的节点上执行对同一条记录的修改,所以它们冲突。如果是被包含关系呢,则表示后面执行的事务是在一个有数据延迟节点上执行的,它跟在它前面的执行的、且从其他节点上执行的、同时也修改了这个记录的事务产生冲突。因为该节点有数据延迟,在其他节点已经执行的事务,还没有在该节点被重放,或被说被执行。

前面讲到,事务消息通过paxos协议实现在全集群范围内一致性广播之后,每个节点都将收到整个集群发生的所有事务,而且所有事务在每个节点内部的排序都是完全相同的。有了这个前提之后,冲突检查就可以在每个节点内部独立完成,无需在节点之间进行通信,每个节点对同一事务进行冲突检查的结果是完全一致的,要么在所有的节点都能检查到冲突,要么都不冲突。理论上不存在这样的情况:某个事务在节点A上检查通过,在节点B上不通过。如果出现,将是非常严重的bug,将造成节点之间数据的不一致。

接下来我们来看一下冲突检测的示意图:

事务的日志经过paxos协议进行全局一致性广播之后,被放入到一个先进先出的消息队列里面,然后被逐个取出来进行验证。比较规则刚才在上一张ppt讲过,利用事务所涉及表记录的主键去写集合(write set)里面查找,如果被命中,则比较事务执行时所基于的数据版本(该数据版本用gtid set 来表示)。这个例子中,是包含关系,所以不冲突。验证通过之后,会将事务日志中所包含的用于验证冲突的信息,也就是事务所操作的表记录的主键,以及事务执行时所基于的数据版本,以条目的形式加入到写集合当中,以供后面的事务来进行冲突验证。讲到这里,大家可能有个疑问:每当事务验证通过之后,就会往这个写集合里面增加条目,那么这个写集合会变得越来越大。的确会如此,但是MGR也考虑到这一点,所以有清理机制,会将过期的条目(记录)从写集合中清理掉。 但在清理的时候,可能会给MGR性能造成影响,后面还会讲到。

我们再来看一下冲突检测的另外一个场景:

事务Ta跟事务Tb,他们操作的记录相同,都是主键为3, 但它们的发起节点不同,事务Ta在节点A上执行,事务Tb在节点B上执行,而且事务所基于的数据版本号也不同。如果实际的执行顺序是Ta->Tb, 这样将不会出现冲突,它们是正常的先后顺序,事务Tb执行时,它对Ta事务的执行结果已经是可见的,它在事务Ta执行后的数据版本上执行,它们是完全正常的先后顺序。但如果Ta 跟Tb 是同时执行的,或者是Ta 晚于Tb 执行,则Ta 实际上是在一个有数据延迟的数据库上执行,跟在其他节点,也就是节点B,已经成功执行的、但还没有在节点A上执行的事务Tb 冲突。

我们刚才讲了比较多的概念性的内容,现在我们来看看,在MGR中,事务执行到底是一个怎样的流程,MGR这部分内容到底是怎样的工作机制。我们从代码层面来剖析,这样有更直观地理解。

我们先来看一下用户线程,也就是会话线程,或者说执行sql的线程,在MGR中,它到底是怎么工作的?

对于用户线程来说,在MGR节点上执行跟在普通节点上执行,SQL的执行过程是完全一模一样的。唯一的区别,就是上面红色的部分,在事务执行到MYSQL_BIN_LOG::commit函数,也就是binlog提交的阶段时,在这个binlog提交阶段的入口处,植入了一个函数, 这个函数的名称为group_replication_trans_before_commit , 这个函数的作用就是将事务的binlog日志写入一个本地广播通道,这个广播通道里的内容后续会被MGR里的一个线程利用paxos协议广播出去的。用户线程将事务日志写入到这个本地广播通道之后,就调用waitTicket函数进入等待状态。 等待的是什么呢? 等待的就是MGR底层线程将这个事务的日志通过paxos协议广播出去,然后进行事务冲突验证。 冲突验证完成之后,就马上唤醒用户线程。 用户线程根据冲突验证的结果,来决定继续提交这个事务,还是回滚事务。

下面我们来详细讲一下MGR的内部流程。  MGR内部主要的功能有两个,第一个是对事务日志通过paxos协议进行全局一致性广播,也就是paxos协议的实现。第二个功能,就是冲突检查,对事务做事务间的冲突检查,保障多个节点并行执行的事务不冲突。

为了实现这两个核心功能,MGR引入了几个线程来处理,主要包含接下来要讲到三个线程:

第一个线程,xcom_taskmain2线程, 简称任务线程,用来调度各种类型的任务,例如发送消息,执行消息等等。

第二个线程,process_notification线程,这个线程是处理消息的线程,但更多的是充当消息中转站的角色,不直接使用消息。

第三个线程,applier线程, 这个是真正执行/处理消息的线程。例如将收到的/或者本地节点产生的包含事务日志的消息进行事务验证,验证完成之后,进行相应的处理。

前面我们讲到,在事务提交时,用户线程将事务日志写入到本地广播通道之后,用户线程就进入等待状态。 这时,MGR的xcom_taskmain2线程,发现本地广播通道存在需要广播的消息(内容)时,将利用paxos协议对该消息进行集群范围内全局一致性广播,消息广播完成之后,就开始调用excute_msg函数,也就是执行消息,但这个消息必须满足不是一个no_op类型的消息,也就是说这个消息是一个有效的消息,需要执行的消息,没有被成功广播的消息是不会被处理的。但这里并不是真正地执行消息,而仅仅是将这个消息push到名称为m_notification_queue的队列里,接下来由process_notification线程对这个消息进行处理。

如图,当process_notification线程发现m_notification_queue队列里面有消息时,将消息取出逐个处理,调用的处理函数为on_message_recived, 我们来看一下这个函数的内容。

这个函数的内容非常简单,主要逻辑就是一段switch代码段, 首先获取消息的类型,然后根据消息的类型,调用不同的处理函数。 如果是事务类型的消息,类型为CT_TRANSACTION_MESSAGE, 则调用handle_transactional_message函数来处理。如果是CT_SINGLE_PRIMARY_MESSAGE类型的消息,则调用handle_single_primary_message函数处理,当然,还会有其他类型的消息,限于ppt片幅的大小,没有展示出所有类型的消息以及它们的处理函数。 下面我们来看一下事务类型的消息是如何处理的,也就是handle_transactional_message函数的逻辑是怎样的。

这个函数对消息的处理特别简单,并没有真正处理这个消息,还是将这个消息push到另外一个队列, 这个队列的名称叫incoming队列。至此,process_notification线程对这个消息的处理就完成了。接下来由另外一个线程,applier线程来处理。

Applier线程会执行applier_thread_handle 这个函数,这个函数的作用就是从incoming 队列里面取出消息,然后根据包类型来调用不同的处理函数。如果是一个data_packet_type类型, 也就是数据类型的包(事务日志里面存放的就是以行为单位的数据),则调用apply_data_packet 函数。该函数后面会调用certification_handler类的函数,最终会调用Certifier类的certify函数进行事务的冲突验证 ,用来检查事务跟事务之间是否有冲突。验证完之后,如果是本地节点发起的事务,将调用releaseticket函数,将正在等待验证结果的用户线程唤醒,用户线程唤醒之后,根据验证结果,来决定继续提交这个事务,还是回滚这个事务。如果是从远端复制过来的事务,如果验证通过,将数据包里面的内容转换成relay log , 然后经过sql线程进行事务重放。如果跟其他事务冲突,将直接丢弃,而这个事务的发起节点,会将这个事务回滚,从而节点之间,数据最终一致。

我们来看一下applier_thread_handle函数的具体代码:

第一行,从incoming队列里面取出头部消息包, 然后根据这个包的不同类型调用不同函数来处理。例如有VIEW_CHANGE_PACKET_TYPE类型,这个类型的包跟节点的加入或者脱离集群有关。还有SINGLE_PRIMARY_PACKET_TYPE类型的包,这种包跟重新选举主库有关,另外还有数据类型的包,也就是包含事务日志的包,DATA_PACKET_TYPE类型,则调用app_data_packet函数,该函数最终会调用冲突验证函数,来对事务进行冲突验证。另外,需要补充说明一下,可能大家会觉得:在MGR的单主模式中,只允许一个节点执行事务,不存在事务冲突,所以无需冲突验证。 事实确实如此,但是无论是在单主模式下,还是多主模式下,冲突检测这个流程都是存在的, 唯一的区别是:如果不需要冲突检测时,不需要再拿事务所涉及的表记录的主健去往写集合里面去查找看是否命中,而是直接跳过这个步骤, 但冲突验证函数依然会被调用,整体流程是一模一样。

刚才讲了这么MGR原理,简单来讲,MGR的工作模式就是:在事务进行binlog提交的入口处,设置了一个门闸,或者说是一个检查站。事务提交时,检查站会对事务进行验证。 检查站验证的流程是:先将事务日志通过paxos协议进行全局一致性广播,广播完成之后,对这个事务进行事务间的冲突检测。如果检测通过,就放行,事务继续提交。如果不通过,事务就回滚。这就是MGR的工作机制。

下面我们将MGR与MYSQL的半同步来进行对比:

通过对比这两个图,我认为最大的差异就是在binlog生成的时间点上面,上面这张图,semi-sync, 事务在本地节点提交时,先生成binlog,然后传递给从库,从库收到之后,变成relay-log,然后通知源库,也就是主库,已经收到binlog, 然后主库继续提交事务,将事务提交流程走完。 而下面这张图,MGR,则是事务执行后,进行提交时,先将事务日志写入本地的广播通道,然后事务日志通过paxos协议进行全局一致性广播,广播完成之后,再进行事务间的冲突验证。如果验证通过, 事务的发起节点的用户线程继续提交该事务,然后生成binlog。 对于其他节点,事务验证通过之后,将事务日志转换成relay log. 如果事务验证失败,则事务的发起节点,回滚该事务,对于其他节点,将事务日志丢弃掉,不再转换成relay log.这样保证了节点间数据的一致性。

我们再继续将MGR与MySQL半同步进行其他方面的对比。

功能上的差异,我们在前面已经讲过,这里不再重复。另外,需要特别关注一下,MGR节点间的网络流量。因为在MGR中,paxos协议的机制远比主从复制的复杂,所以节点间的网络流量要大很多,大家测试的时候可以对比一下。

另外,就是性能上的差异。大家可能会觉得,MGR的通讯协议比半同步复制复杂,工作机制也比半同步复杂,所以比较容易会得出MGR比半同步的性能要差,事实是否真的如此,建议大家动手测试一下。另外,需要补充一点的就是,MGR有流控功能,目的是避免从节点的数据同步延迟过大, 但半同步复制没有这个功能。为了公平测试性能,建议将MGR的流控功能先关闭,让它们在同一个技术平台上测试,否则测得的MGR性能会比较差。因为影响MGR性能的因素比较多,不同的硬件环境,网络环境,不同的参数得出的结果可能不一样,所以建议大家自己动手测试。简单说一下我们的测试结果,供大家参考。如果在网络环境比较好的情况下,节点间的网络响应延迟比较低的时候,MGR的性能可能比半同步的性能稍微好那么一点点。如果节点间网络延迟比较大,半同步的性能就会比MGR要好。

最后一部分,将介绍在MGR上的一些实践,可能对大家使用MGR更有实际地指导意义。

首先我们来看一下网络对MGR的影响。我建议大家至少从这三个场景测试网络对MGR的影响,以便深刻地了解MGR性能与稳定性对网络到底有多大依赖。

第一个场景: 三节点的集群,其中一个secondary(从)节点网络响应延迟比较高,它是否会影响整体性能? 如果没有进行测试,大家怎么看? 可能会有一部分朋友会认为paxos协议是多数派原则,一个节点网络响应延迟不影响MGR集群整体性能。这个结论是否正确,建议大家自己动手测试一下。从我自己的测试结果来看,还是存在较大的影响。原因推测为:paxos 协议虽然是多数派原则,但是每个节点都是参与者,节点间都会进行通讯,如果某个节点网络响应延迟,将拖累集群整体的通讯效率,从而影响整体的性能。如果这个节点宕机,则不再参与集群内部的通讯,性能反而会提升。因此,在实际的生产环境中,如果某个节点因为出现网络问题,而拖累整个集群的性能,直接将其关机也是一种应急方法。

第二个场景: 主节点突然跟其他两个节点网络隔离,另外两个节点还能互通。主节点会怎样? 另外两个节点会怎么样?因为主节点突然跟其他两个节点不通,正在执行的事务的日志没有办法通过paxos协议广播出去,事务提交无法继续进行,所以主节点将hang住。另外两个节点,跟主节点不通,但两个节点之间可以通讯,它们则认为主节点宕机,然后它们俩之间进行重新选主,将选择一个节点作为新主库,组成一个两个节点的新集群。

第三个场景:三个节点相互不通,各自孤立。这种情况跟上面的场景类似,主节点hang住,另外两个节点之间也网络不通,则无法进行重新选举主库,直到网络恢复后才可能恢复正常。需要特别注意的是,刚才说的是可能恢复正常,也就是说,也可能存在网络恢复之后,集群却没有自动恢复正常的情况,需要人工介入处理。

当我们测试完之后,就会比较深刻的理解到,网络的稳定性对MGR集群到底有多重要。

另外,需要特别注意这一点,就是当每个节点因为某些原因,变成一个非MGR模式的节点, 也就是说变成一个单节点时,这个时候是理应不允许有“业务流量”闯入的。采用多节点访问接入+多主模式的MGR集群时,更应该谨慎考虑这个潜在风险,以避免将数据写“脏”,破坏集群内数据的整体一致性。 mysql 5.7.19的release notes中提到一个关于read_only的bug , 也建议大家将super_read_only参数在配置文件就设置为1 .

还有,对这个参数,也需要特别谨慎,group_replication_bootstrap_group 参数。我们在日常运维MGR过程中,避免不了会使用start group_replication命令将某个节点加入MGR集群。如果这个参数设置不正确,可能造成某个节点数据丢失。 原因就是当参数group_replication_bootstrap_group设置为on的时候,执行start group_replication命令时,当前节点会作为初始节点启动一个新的MGR集群,同时该节点的gtid_executed会增加一个事务。如果忽略这点,很容易犯错误,造成某个节点数据丢失。ppt上演示了数据丢失的全过程,请大家留意。

为了避免出现这种情况,有如下建议:

前面将MGR与SEMI-SYNC进行了功能以及性能上的对比,性能上基本没有差别,但功能上MGR远强于SEMI-SYNC, 但MGR目前在国内并没有被广泛使用,原因是什么? 我想应该是稳定性。

不知道大家有没有测试过,或者使用过MGR .对MGR进行过压力测试的朋友可能会发现这个现象:在低负荷的情况下,MGR还是比较平稳的,但是,在高负荷的情况下,几乎百分百地会发现性能抖动的现象。原因是什么?

原因如下,影响MGR稳定性的因素有: 1.网络,刚才已经讲过,这个应该也是大家的共识,paxos协议对网络延迟以及网络的稳定性依赖较大。 2。cpu,这个因素可能大家之前没有意识到。为什么说cpu对MGR性能稳定性比较大呢?前面我们讲了MGR的内部工作流程,大家有没有注意到,事务的日志首先在全局范围内作一致性广播,然后进入各个环节的队列,该环节处理完成之后再进入下一个环节的队列,且每个环节都是由一个独立的线程来完成。简单来说,MGR底层的工作流是一个全局的串行工作流,如果某个MGR线程没有及时获取到cpu, 则无法进行工作,整个MGR流程将堵塞,因此正在执行的事务在提交阶段被堵塞,造成事务无法完成提交,直到该线程继续正常工作为止。3。就是工程实现“缺陷”, 前面讲过,事务冲突检测通过之后,需要将事务所操作的表的记录的主键等信息加入到写集合当中,以供后面的事务进行冲突检测。如果只添加,不清理的话,写集合会越来越大,所以,写集合里面多余的条目要被清理掉。但是,在清理的时候,清理函数certifier::garbage_collect会锁住全局锁lock_certification_info, 而进行事务冲突验证的函数也需要这个锁,所以这两个函数的执行是互斥的。 当进行写集合的垃圾回收的时候,事务的提交是要被堵塞的。因为写集合里面的条目是一条一条清理的,如果需要清理的条目特别多,那垃圾回收的时间就会比较长,整个集群被堵塞的时间就比较长。当需要清理的条目比较少的时候,垃圾回收的时间会比较短,用户线程提交事务时可能感知不到,不会造成堵塞。但如果之前执行过非常大的事务,或者其它的因素,需要清理大量过期/垃圾条目时,将会造成用户线程提交事务时被堵塞,性能出现严重抖动。

这个是我们在测试环境中,现场捕获的一个场景,当时发现MGR的TPS急剧下降, 然后现场抓了stack.

用户线程都执行到waitTicket函数,等到MGR对事务进行冲突验证。但MGR执行冲突验证的函数certifier::certify自己也处于等待状态,等待获取lock_certification_info全局互斥锁,而这把锁,正在被写集合垃圾回收函数certifier::garbage_collect持有,正在做垃圾清除。

除刚才讲到的这些因素影响MGR的稳定性之外,另外就是bug .

这个BUG还是相当严重的,也比较容易出现。在我们的测试中,几乎100%的出现。现象就是,当主节点的事务负荷比较高的时候,当某个节点新加入集群,将造成整个集群hang住,且不能自我恢复。唯一的解决办法就是将整个集群的mysqld进程重启。上面是出现这个bug时,主节点跟从节点各自的错误日志中出现的信息,信息概要就是无法识别某个packet, 原因是这个backet 被截断了。更详细的原因参考bug 87701, 好在这个bug已经在5.7.21上解决。

下面也是一个关于从节点无法加入集群的bug , 但相比上面的bug,这个影响要小非常多,它没有影响主节点的可用性。  这个也是我们在测试过程中发现的bug.

另外,还有一些其它的bug, 在这里列出来供大家参考。这些bug 是官方公布并已经解决的。因此,如果使用MGR, 还是建议使用高版本,这样bug相对少些,至少已经解决了不少bug.

最后讲一下个人对运维MGR的思考。相比半同步,MGR确实具有半同步无法对标的功能,这也是非常诱惑数据库运维人员的原因,想去使用它,体验它的强大功能。而且MGR看似各节点对等,支持多节点写入,数据强一致(理论上),这些特性甚至会给大家带来一种MGR比MySQL半同步更容易运维的错觉。但作为专业运维人员的我们也知道,错觉始终是错觉,从MGR真正的被使用的范围就可以看出,大家都非常理智------只是用MGR在不重要的系统上试水,并没有大规模的推广,当然,也还有很多朋友可能还没有去测试过MGR。 对于MGR,我个人的观点是这样的:MGR确实是一个比较新生的事物,当前也存在一些缺陷。但作为一个专业运维人员,即使产品有缺陷,我们也可以运维。 对于运维MGR,我们确实需要考虑得更多:1. 我们需要尽可能多去了解MGR的缺陷,对已知缺陷做到心中有数,能规避的,通过设定规范来规避。2。我们针对可能出现的问题,做好预案。在预案范围之外的,使用终极手段,例如重启。3。MGR可能故障的概率比较高,所以特别需要考虑自动化地处理故障。另外,特别补充一点,就是MGR理论上是保证各节点之间数据完全一致,是否我们真的就不折不扣地完全相信它?如果数据不一致,这个风险我们能否承担? 如果需要验证数据一致性,我们该如何验证?因为MGR不支持语句模式的binlog设置,所以我们不能使用percona公司的开源软件pt-table-checksum来做数据一致性校验。 非主从模式的数据一致性校验,很多场景都存在,网上可能也有相关的方案。我个人的想法是,依然借鉴pt-table-checksum校验的方法,将数据按主建进行范围切片,先采用不加锁的方式用相同的SQL校验各节点的数据的CRC32校验值。如果一致,检测通过。如果不一致,再加锁检查。绝大部分的数据是存量数据,是不需要加锁查询的。

以上是本次分享的全部内容。谢谢大家!

徐春阳,曾供职国内一线互联网公司,2015年3月进入信息科技部运维部门数据库团队工作之后,从零开始建设开源数据库MySQL相关的工作。同时,从项目初期开始,就全面负责民生银行分布式核心系统所使用的开源数据库MySQL相关工作,及时并成功解决该项目在研发、测试、以及上线过程中遇到的与数据库相关的各种疑难问题。数据库运维经验丰富,且热衷钻研开源数据库技术,并乐于分享,已在其个人公众号发布较多篇技术文章,获得大量读者认可。