注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

网易杭研后台技术中心的博客

 
 
 
 
 

日志

 
 

Partial Transaction In MySQL Replication  

来自郭忆   2013-05-29 23:05:41|  分类: 默认分类 |举报 |字号 订阅

  下载LOFTER 我的照片书  |

  RDS 在实现高可用功能的过程中,遇到了一个MySQL Partial Transaction的问题,希望能够跟大家分享一下问题的解决思路。

  首先先介绍一下问题产生的背景,RDS的高可用是基于MySQL复制实现的。我们首先简单的回顾一下MySQL复制的基本原理。

  Partial Transaction In MySQL Replication - 网易杭研后台技术中心 - 网易杭研后台技术中心的博客

      MySQL复制一共涉及3个线程,分别是Slave上的IO线程和SQL线程,以及Master上的dump线程。主库上的事务在提交时会写Binlog,注意是在事务提交的时候,才写Binlog,所以MySQL就可以按照事务的提交顺序而非每条语句的顺序记录BinlogBinlog的更新会唤醒Master上的Dump线程,Dump线程就会发送SQL EventSlave上监听的IO 线程,IO线程会将监听到的SQL Event写到Relay log中,然后由SQL 线程去执行Relay log中的二进制日志。注意Slave上的IO线程是WAL的,即会完成写日志到RelayLog中才返回给Master成功。

   

    为了保证主从数据的一致性,我们调整了MySQL事务提交的次序,即先写Binlog,然后唤醒Dump线程,发送SQLEvent,收到从机的确认后,主机才写Redo log提交事务。这样就保证了,没有发送到从机的事务是绝对不会被提交的。在主机发生宕机以后,我们首先在从机上执行stop slave io_thread,停掉Slave上的IO线程,此时主上即使有事务提交,由于无法得到从机的响应,也无法提交,这样即避免了脑裂的场景,也防止Relay log继续写入。然后剩下的工作就要保证Relay Log中的SQL Event能够完全回放到从库上。其实Slave上有两个位置来分别记录IO线程读取到主库上的Binlog的位置即Read_Master_Log_Pos和SQL 线程执行到的主库上的Binlog的位置Exec_Master_Log_Pos,由于这两个位置都是Master上的Binlog的位置,所以很容易想到的方案就是去判断Read_Master_Log_PosExec_Master_Log_Pos是否相等,如果相等,则表示SQL线程已经完全执行完IO线程接到的SQL Event了。注意,我前面一直都在强调IO 线程写入Relay log的单位不是一个事物,即对于一个大事务而言,完全可能出现IO线程写入Relay log中的是一个不完整的事务,了解MHA的同学一定知道,MHA定义为叫Partical Transaction。此时,由于最后一个是一个不完整的事务,SQL线程是不会继续执行的,所以Exec_Master_Log_PosRead_Master_Log_Pos永远不可能相等,这样上面的判断逻辑就有问题了。

   Partial Transaction In MySQL Replication - 网易杭研后台技术中心 - 网易杭研后台技术中心的博客

   

      耳听为虚,眼见为实,下面我们来对上面的设想做一个测试,在主库上开启一个事务,这个事务对数据库一条记录进行10W次更新,然后提交该事务,同时去kill掉主上的MySQL进程。下面就是见证奇迹的时刻了。

    Partial Transaction In MySQL Replication - 网易杭研后台技术中心 - 网易杭研后台技术中心的博客

   
        Slave上原先相等的Read_Master_Log_PosExec_Master_Log_Pos开始发生变化,Read_Master_Log_Pos开始快速增长,但是Exec_Master_Log_Pos一致没变。
     Partial Transaction In MySQL Replication - 网易杭研后台技术中心 - 网易杭研后台技术中心的博客
   
     最终Read_Master_Log_Pos的位置是2801678,Exec_Master_Log_Pos始终是321。此时我们打开RelayLog,发现RelayLog的最后一个Binlog EventRollBack

  Partial Transaction In MySQL Replication - 网易杭研后台技术中心 - 网易杭研后台技术中心的博客


     即此时该事务在Relay Log中是一个不完整的事务。而从机会自动在RelayLog中加一个RollBackEvent
   
   在了解了上述出现的问题后,我们需要重新思考如果判断SQL 线程已经将RelayLog完全回放完毕。其实Relay Log就是Binlog的转储文件,由一系列的Event组成。我们首先判断Relay Log的末尾是否有RollBack Event,如果没有,则表明Exec_Master_Log_PosRead_Log_Master_Pos是一定会相等。如果有,则去判断当前Exec_Master_Log_Pos的下一个位置是不是Begin Event,如果不是,则等待。如果是,则判断Begin Event到末尾还有Commit Event,如果有,则等待,如果没有,则表明已完全回放完毕。这里无需要担心如果是用户发起的RollBack情况,因为即使是用户发起的RollBack,其到BenginSQL Event本身也是要回滚的,所以无需担心其没有在Slave上执行。

具体算法如下:

 

Partial Transaction In MySQL Replication - 网易杭研后台技术中心 - 网易杭研后台技术中心的博客
   这样我们就可以判断RelayLog中的SQL Event是否完全回放完毕。
 



 



 

 
  评论这张
 
阅读(532)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017