频道栏目
首页 > 数据库 > MySQL > 正文
MySQL半同步before_send_event实例讲解
2018-01-02 09:14:44         来源:yanzongshuai的专栏  
收藏   我要投稿

mysql_binlog_send-->before_send_event --> repl_semi_before_send_event

--> repl_semisync.updateSyncHeader

int repl_semi_before_send_event(Binlog_transmit_param *param,
                                unsigned char *packet, unsigned long len,
                                const char *log_file, my_off_t log_pos)
{
  return repl_semisync.updateSyncHeader(packet,
					log_file,
					log_pos,
					param->server_id);
}
int ReplSemiSyncMaster::updateSyncHeader(unsigned char *packet,
					 const char *log_file_name,
					 my_off_t log_file_pos,
					 uint32 server_id)
{
  const char *kWho = "ReplSemiSyncMaster::updateSyncHeader";
  int  cmp = 0;
  bool sync = false;

  /*
  1、如果master没有开启半同步或者slave没有开启半同步,直接返回
  */
  if (!getMasterEnabled() || !is_semi_sync_slave())
    return 0;

  function_enter(kWho);
  /*
  2、LOCK_binlog_锁内,下面代码串行,再次判断master是否开启半同步并且半同步是否正常
  */
  lock();
  /* This is the real check inside the mutex. */
  if (!getMasterEnabled())
    goto l_end; // sync= false at this point in time
  if (is_on())
  {
    /*
	1、当前的event的Log_file_name和pos小于reply值,表示这个event已经收到ack了,不需要再等
	*/
    if (reply_file_name_inited_)
    {
      cmp = ActiveTranx::compare(log_file_name, log_file_pos,
                                 reply_file_name_, reply_file_pos_);
      if (cmp <= 0)
      {
        /* If we have already got the reply for the event, then we do
         * not need to sync the transaction again.
         */
        goto l_end;
      }
    }
    /*
	2、如果当前event的位置大于最小等待事务ack的位置,说明这个event可能也需要等待ack
	*/
    if (wait_file_name_inited_)
    {
      cmp = ActiveTranx::compare(log_file_name, log_file_pos,
                                 wait_file_name_, wait_file_pos_);
    }
    else
    {
      cmp = 1;
    }
    /*
	2.1 只有cmp>=0时,才需要进行判断该event是不是事务的最后一个event。只有事务的最后一个event
	    才需要等待接收ACK
	*/
    if (cmp >= 0)
    {
      /* 
      注:active_tranxs_管理的是事务的最后一个event。通过当前event的位置hash到active_tranxs节点中
	      entry->hash_next_管理的是同一个hash key的事务的最后一个event,所以需要这个链表进行遍历
      */
      assert(active_tranxs_ != NULL);
      sync = active_tranxs_->is_tranx_end_pos(log_file_name,
                                               log_file_pos);
    }
  }
  /*
  3、半同步发生异常,变成异步了:当前event已经是当前最新的binlog位置,表示slave已经跟上master?
     这个event需要等待ACK
     
  */
  else
  {
    if (commit_file_name_inited_)
    {
      int cmp = ActiveTranx::compare(log_file_name, log_file_pos,
                                     commit_file_name_, commit_file_pos_);
      sync = (cmp >= 0);
    }
    else
    {
      sync = true;
    }
  }
l_end:
  unlock();

  /* 
  4、设置包头,添加semi-sync的flag,表示需要进行等待ACK,即slave也需要回复ack
  */
  if (sync)
  {
    (packet)[2] = kPacketFlagSync;
  }

  return function_exit(kWho, 0);
}
点击复制链接 与好友分享!回本站首页
上一篇:mysql语法之#与$符号关键字的用法讲解
下一篇:mysql设置事务的隔离级别讲解及脏读、不可重复读、幻读的讲述
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站