mysql server id 冲突_MySQLSlave同一server_id的冲突原因分析

当两个Slave使用相同server_id连接MasterServer时,Master会先注销已有线程,再注册新的线程,导致旧线程被kill。这是MySQLReplication的重连机制,确保Slave在断开后能重新注册并获取binlog,保持数据同步。

今天分析一个诡异问题,一个模拟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:

{

if (!register_slave(thd, (uchar*)packet, packet_length))

my_ok(thd);

break;

}

在注册Slave线程的时候会发生什么呢?我们略去无用的代码直接看重点:(repl_failsafe.cc)

代码如下

int register_slave(THD* thd, uchar* packet, uint packet_length)

{

int res;

SLAVE_INFO *si;

uchar *p= packet, *p_end= packet + packet_length;

.... //省略

if (!(si->master_id= uint4korr(p)))

si->master_id= server_id;

si->thd= thd;

pthread_mutex_lock(&LOCK_slave_list);

unregister_slave(thd,0,0); //关键在这里,先取消注册server_id相同的Slave线程

res= my_hash_insert(&slave_list, (uchar*) si); //把新的Slave线程注册到slave_list

pthread_mutex_unlock(&LOCK_slave_list);

return res;

.....

}

这是什么意思呢?这就是重连机制,slave_list是一个Hash表,server_id是Key,每一个线程注册上来,需要删掉同样server_id的Slave线程,再把新的Slave线程加到slave_list表中。

线程注册上来后,请求Binlog,发送COM_BINLOG_DUMP请求,Master会发送binlog给Slave,代码如下:

代码如下

case COM_BINLOG_DUMP:

{

ulong pos;

ushort flags;

uint32 slave_server_id;

status_var_increment(thd->status_var.com_other);

thd->enable_slow_log= opt_log_slow_admin_statements;

if (check_global_access(thd, REPL_SLAVE_ACL))

break;

/* TODO: The following has to be changed to an 8 byte integer */

pos = uint4korr(packet);

flags = uint2korr(packet + 4);

thd->server_id=0; /* avoid suicide */

if ((slave_server_id= uint4korr(packet+6))) // binlog.server_id==0

kill_zombie_dump_threads(slave_server_id);

thd->server_id = slave_server_id;

general_log_print(thd, command, "Log: '%s' Pos: %ld", packet+10,

(long) pos);

mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags); //不断的发送日志给slave端

unregister_slave(thd,1,1); //发送完成后清理Slave线程,因为执行到这一步肯定是binlog dump线程被kill了

/* fake COM_QUIT -- if we get here, the thread needs to terminate */

error = TRUE;

break;

}

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)

{

if (thd->server_id)

{

if (need_mutex)

pthread_mutex_lock(&LOCK_slave_list);

SLAVE_INFO* old_si;

if ((old_si = (SLAVE_INFO*)hash_search(&slave_list,

(uchar*)&thd->server_id, 4)) &&

(!only_mine || old_si->thd == thd)) //拿到slave值

hash_delete(&slave_list, (uchar*)old_si); //从slave_list中拿掉

if (need_mutex)

pthread_mutex_unlock(&LOCK_slave_list);

}

}

这就可以解释同样的server_id为什么会被kill,因为一旦注册上去,就会现删除相同server_id的Slave线程,然后把当前的Slave加入,这是因为有时Slave断开了,重新请求上来,当然需要踢掉原来的线程,这就是线程重连机制。

本条技术文章来源于互联网,如果无意侵犯您的权益请点击此处反馈版权投诉

本文系统来源:php中文网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值