你的位置:首页 > 数据库

[数据库]slave IO流程之二:注册slave请求和dump请求


slave IO流程已经在http://www.cnblogs.com/onlyac/p/5815566.html中有介绍

这次我们要探索注册slave请求和dump请求的报文格式和主要流程。

一、注册slave请求

在slave IO连接完数据库后,slave IO接着在主库里注册自己,以便后续不需要提供slave IO登陆的信息如用户名密码等。

1.注册slave请求的报文格式

 1 1       [15] COM_REGISTER_SLAVE 2 4       server-id 3 1       slaves hostname length 4 string[$len]  slaves hostname 5 1       slaves user len 6 string[$len]  slaves user 7 1       slaves password len 8 string[$len]  slaves password 9 2       slaves mysql-port10 4       replication rank11 4       master-id

View Code

(1)报文的类型COM_REGISTER_SLAVE

(2)slave服务器的id,该id唯一并且只能通过my.cnf配置文件改变

(3)slave主机名长度

(4)slave主机名

(5)slave在主库登陆用户名长度

(6)slave在主库登陆用户名

(7)slave在主库登陆的密码长度

(8)slave在主库登陆的密码

(9)slave的mysql端口

(10)(11)这两个都是0,不用去关注

2.在register_slave_on_master中

 1  int4store(pos, server_id); pos+= 4; 2  pos= net_store_data(pos, (uchar*) report_host, report_host_len); 3  pos= net_store_data(pos, (uchar*) report_user, report_user_len); 4  pos= net_store_data(pos, (uchar*) report_password, report_password_len); 5  int2store(pos, (uint16) report_port); pos+= 2; 6  /*  7   Fake rpl_recovery_rank, which was removed in BUG#13963, 8   so that this server can register itself on old servers, 9   see BUG#49259.10  */11  int4store(pos, /* rpl_recovery_rank */ 0);  pos+= 4;12  /* The master will fill in master_id */13  int4store(pos, 0);          pos+= 4;

View Code

这是除了第一个没有的在1中的报文格式,然后通过simple_command发送出去。

1 #define simple_command(mysql, command, arg, length, skip_check) \2  ((mysql)->methods \3   ? (*(mysql)->methods->advanced_command)(mysql, command, 0, \4                       0, arg, length, skip_check, NULL) \5   : (set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate), 1))

View Code

该函数指向cli_advanced_command。

(1)在li_advanced_command中

在通过函数net_write_command写该报文

 1  if (net_write_command(net,(uchar) command, header, header_length, 2       arg, arg_length)) 3  { 4   DBUG_PRINT("error",("Can't send command to server. Error: %d", 5       socket_errno)); 6   if (net->last_errno == ER_NET_PACKET_TOO_LARGE) 7   { 8    set_mysql_error(mysql, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate); 9    goto end;10   }11   end_server(mysql);12   if (mysql_reconnect(mysql) || stmt_skip)13    goto end;14   15   MYSQL_TRACE(SEND_COMMAND, mysql, (command, header_length, arg_length, header, arg));16   if (net_write_command(net,(uchar) command, header, header_length,17        arg, arg_length))18   {19    set_mysql_error(mysql, CR_SERVER_GONE_ERROR, unknown_sqlstate);20    goto end;21   }22  }

View Code

(2)在net_write_command中

1  buff[4]=command;        /* For first packet */

View Code

这个写了该报文的类型,

 1  if (length >= MAX_PACKET_LENGTH) 2  { 3   /* Take into account that we have the command in the first header */ 4   len= MAX_PACKET_LENGTH - 1 - head_len; 5   do 6   { 7    int3store(buff, MAX_PACKET_LENGTH); 8    buff[3]= (uchar) net->pkt_nr++; 9    if (net_write_buff(net, buff, header_size) ||10      net_write_buff(net, header, head_len) ||11      net_write_buff(net, packet, len))12    {13     MYSQL_NET_WRITE_DONE(1);14     DBUG_RETURN(1);15    }16    packet+= len;17    length-= MAX_PACKET_LENGTH;18    len= MAX_PACKET_LENGTH;19    head_len= 0;20    header_size= NET_HEADER_SIZE;21   } while (length >= MAX_PACKET_LENGTH);22   len=length;     /* Data left to be written */23  }24  int3store(buff, static_cast<uint>(length));25  buff[3]= (uchar) net->pkt_nr++;26  rc= MY_TEST(net_write_buff(net, buff, header_size) ||27        (head_len && net_write_buff(net, header, head_len)) ||28        net_write_buff(net, packet, len) || net_flush(net));

View Code

这所以这样写是因为每个报文有个这样头

1 if (!skip_check)2  {3   result= ((mysql->packet_length= cli_safe_read_with_ok(mysql, 1, NULL)) ==4       packet_error ? 1 : 0);

View Code

(3)mysql协议的公共报文头部

每个报文都有一个这样的头,这是忘记在上一章讲的

View Code

第一个是这个报文的长度(以字节为单位),第二个是这个报文的系列号,当然发送的内容原来就是一个报文,但是太长分成多个,第三个就是报文本身

对于超过16M的报文会这样发送

View Code

 二、dump请求

1.dump请求的报文格式

dump有两种格式:COM_BINLOG_DUMP_GTID和COM_BINLOG_DUMP

在slave IO的情形下,一般会使用COM_BINLOG_DUMP

为此,在此仅仅介绍COM_BINLOG_DUMP的格式

1 1       [12] COM_BINLOG_DUMP2 4       binlog-pos3 2       flags4 4       server-id5 string[EOF]  binlog-filename

View Code

(1)报文的类型COM_BINLOG_DUMP

(2)请求binlog的写的位置

(3)一般为COM_BINLOG_DUMP_NO_BLOCK类型

(4)slave IO的所在服务器的服务器编号,和slave注册协议中的那个一致

(5)当前需要读的binlog文件名

2.在函数request_dump中

 1   int4store(ptr_buffer, DBUG_EVALUATE_IF("request_master_log_pos_3", 3, 2                      static_cast<uint32>(mi->get_master_log_pos()))); 3   ptr_buffer+= ::BINLOG_POS_OLD_INFO_SIZE; 4   // See comment regarding binlog_flags above. 5   int2store(ptr_buffer, binlog_flags); 6   ptr_buffer+= ::BINLOG_FLAGS_INFO_SIZE; 7   int4store(ptr_buffer, server_id); 8   ptr_buffer+= ::BINLOG_SERVER_ID_INFO_SIZE; 9   memcpy(ptr_buffer, mi->get_master_log_name(), BINLOG_NAME_INFO_SIZE);10   ptr_buffer+= BINLOG_NAME_INFO_SIZE;11 12   command_size= ptr_buffer - command_buffer;13   DBUG_ASSERT(command_size == (allocation_size - 1));

View Code

同样地是COM_BINLOG_DUMP的格式。

这边也使用simple_command(mysql, command, command_buffer, command_size, 1)写入。