今天分析一个诡异问题,一个模拟Slave线程的程序,不断的被Master Server给kill掉,最终发现是因为有两个Slave使用同样一个server id去连接Master Server,为什么两个Slave用同一个server id会被Master Server给Kill呢?分析了源码,这源于MySQL Replication
我们首先看看一个Slave注册到Master会发生什么,首先Slave需要向Master发送一个COM_REGISTER_SLAVE类型的请求(sql_parse.cc)命令请求,这里Master会使用register_slave函数注册一个Slave到slave_list。
代码如下 | 复制代码 |
case COM_REGISTER_SLAVE: |
在注册Slave线程的时候会发生什么呢?我们略去无用的代码直接看重点:(repl_failsafe.cc)
代码如下 | 复制代码 |
int register_slave(THD* thd, uchar* packet, uint packet_length) |
这是什么意思呢?这就是重连机制,slave_list是一个Hash表,server_id是Key,每一个线程注册上来,需要删掉同样server_id的Slave线程,再把新的Slave线程加到slave_list表中。
线程注册上来后,请求Binlog,发送COM_BINLOG_DUMP请求,Master会发送binlog给Slave,代码如下:
代码如下 | 复制代码 |
case COM_BINLOG_DUMP: status_var_increment(thd->status_var.com_other); /* TODO: The following has to be changed to an 8 byte integer */ general_log_print(thd, command, "Log: '%s' Pos: %ld", packet+10, |
mysql_binlog_send函数在sql_repl.cc,里面是轮询Master binlog,发送给Slave。
再来简单看看unregister_slave做了什么(repl_failsafe.cc):
代码如下 | 复制代码 |
void unregister_slave(THD* thd, bool only_mine, bool need_mutex) SLAVE_INFO* old_si; if (need_mutex) |
这就可以解释同样的server_id为什么会被kill,因为一旦注册上去,就会现删除相同server_id的Slave线程,然后把当前的Slave加入,这是因为有时Slave断开了,重新请求上来,当然需要踢掉原来的线程,这就是线程重连机制。