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-port 10 4 replication rank 11 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协议的公共报文头部
每个报文都有一个这样的头,这是忘记在上一章讲的