本文内容遵从CC版权协议, 可以随意转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://www.penglixun.com/tech/database/mysql_multi_slave_same_serverid.html 今天分析一个诡异问题,一个模拟Slave线程的程序,不断的被Master Ser
本文内容遵从CC版权协议, 可以随意转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://www.penglixun.com/tech/database/mysql_multi_slave_same_serverid.html
今天分析一个诡异问题,一个模拟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。
<span style="color: #0000ff">case</span> COM_REGISTE<em>本文来源[email protected]搞@^&代*@码)网5</em>R_SLAVE<span style="color: #008080">:</span> <span style="color: #008000">{</span> <span style="color: #0000ff">if</span> <span style="color: #008000">(</span><span style="color: #000040">!</span>register_slave<span style="color: #008000">(</span>thd, <span style="color: #008000">(</span>uchar<span style="color: #000040">*</span><span style="color: #008000">)</span>packet, packet_length<span style="color: #008000">)</span><span style="color: #008000">)</span> my_ok<span style="color: #008000">(</span>thd<span style="color: #008000">)</span><span style="color: #008080">;</span> <span style="color: #0000ff">break</span><span style="color: #008080">;</span> <span style="color: #008000">}</span>
在注册Slave线程的时候会发生什么呢?我们略去无用的代码直接看重点:(repl_failsafe.cc)
<span style="color: #0000ff">int</span> register_slave<span style="color: #008000">(</span>THD<span style="color: #000040">*</span> thd, uchar<span style="color: #000040">*</span> packet, uint packet_length<span style="color: #008000">)</span><span style="color: #008000">{</span> <span style="color: #0000ff">int</span> res<span style="color: #008080">;</span> SLAVE_INFO <span style="color: #000040">*</span>si<span style="color: #008080">;</span> uchar <span style="color: #000040">*</span>p<span style="color: #000080">=</span> packet, <span style="color: #000040">*</span>p_end<span style="color: #000080">=</span> packet <span style="color: #000040">+</span> packet_length<span style="color: #008080">;</span>.... <span style="color: #666666">//省略</span> <span style="color: #0000ff">if</span> <span style="color: #008000">(</span><span style="color: #000040">!</span><span style="color: #008000">(</span>si<span style="color: #000040">-</span><span style="color: #000080">></span>master_id<span style="color: #000080">=</span> uint4korr<span style="color: #008000">(</span>p<span style="color: #008000">)</span><span style="color: #008000">)</span><span style="color: #008000">)</span> si<span style="color: #000040">-</span><span style="color: #000080">></span>master_id<span style="color: #000080">=</span> server_id<span style="color: #008080">;</span> si<span style="color: #000040">-</span><span style="color: #000080">></span>thd<span style="color: #000080">=</span> thd<span style="color: #008080">;</span> pthread_mutex_lock<span style="color: #008000">(</span><span style="color: #000040">&</span>LOCK_slave_list<span style="color: #008000">)</span><span style="color: #008080">;</span> unregister_slave<span style="color: #008000">(</span>thd,<span style="color: #0000dd">0</span>,<span style="color: #0000dd">0</span><span style="color: #008000">)</span><span style="color: #008080">;</span> <span style="color: #666666">//关键在这里,先取消注册server_id相同的Slave线程</span> res<span style="color: #000080">=</span> my_hash_insert<span style="color: #008000">(</span><span style="color: #000040">&</span>slave_list, <span style="color: #008000">(</span>uchar<span style="color: #000040">*</span><span style="color: #008000">)</span> si<span style="color: #008000">)</span><span style="color: #008080">;</span> <span style="color: #666666">//把新的Slave线程注册到slave_list</span> pthread_mutex_unlock<span style="color: #008000">(</span><span style="color: #000040">&</span>LOCK_slave_list<span style="color: #008000">)</span><span style="color: #008080">;</span> <span style="color: #0000ff">return</span> res<span style="color: #008080">;</span>.....<span style="color: #008000">}</span>