MySQL Slave同一server_id的冲突原因分析
发布:smiling 来源: PHP粉丝网 添加日期:2014-10-17 13:26:18 浏览: 评论:0
今天分析一个诡异问题,一个模拟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 //phpfensi.com
- 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))) // mysqlbinlog.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断开了,重新请求上来,当然需要踢掉原来的线程,这就是线程重连机制.
Tags: MySQL Slave server_id
- 上一篇:MySQL的replace into详解
- 下一篇:常用mysql几条sql语句
相关文章
- ·怎样使MySQL安全以对抗解密高手(2013-11-11)
- ·MYSQL用户root密码为弱口令的攻击(2013-11-11)
- ·Mysql数据库的安全配置、实用技巧(2013-11-11)
- ·Mssql和Mysql的安全性分析(2013-11-11)
- ·MySQL安全问题的一点心得(2013-11-11)
- ·PHP常用MySql操作(2013-11-13)
- ·MySQL数据库下载漏洞攻击技术(2013-11-14)
- ·MySQL3.23.31之前版本的安全漏洞(2013-11-14)
- ·通过Mysql的语句生成后门木马的方法(2013-11-14)
- ·MySQL服务器内部安全数据目录访问(2013-11-14)
- ·MySQL数据库中的安全解决方案(2013-11-14)
- ·如何保护MySQL 中的重要数据(2013-11-14)
- ·为你的MySQL数据库加铸23道安全门(2013-11-14)
- ·Mysql的Root密码遗忘的解决办法(2013-11-14)
- ·如何开启MySQL的远程帐号(2013-11-14)
- ·我的Mysql碰到了 1067 错误(2013-11-27)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)