国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數(shù)據(jù)庫 > MySQL > 正文

MySQL Slave同一server_id的沖突原因分析

2024-07-24 12:39:20
字體:
供稿:網(wǎng)友

今天分析一個詭異問題,一個模擬Slave線程的程序,不斷的被Master Server給kill掉,最終發(fā)現(xiàn)是因為有兩個Slave使用同樣一個server id去連接Master Server,為什么兩個Slave用同一個server id會被Master Server給Kill呢?分析了源碼,這源于MySQL Replication的重連機制.

我們首先看看一個Slave注冊到Master會發(fā)生什么,首先Slave需要向Master發(fā)送一個COM_REGISTER_SLAVE類型的請求(sql_parse.cc)命令請求,這里Master會使用register_slave函數(shù)注冊一個Slave到slave_list,代碼如下:

  1. case COM_REGISTER_SLAVE: 
  2.   { 
  3.     if (!register_slave(thd, (uchar*)packet, packet_length)) 
  4.       my_ok(thd); 
  5.     break
  6.   } 

在注冊Slave線程的時候會發(fā)生什么呢?我們略去無用的代碼直接看重點,repl_failsafe.cc代碼如下:

  1. int register_slave(THD* thd, uchar* packet, uint packet_length) 
  2.   int res; 
  3.   SLAVE_INFO *si; 
  4.   uchar *p= packet, *p_end= packet + packet_length; 
  5. .... //省略 
  6.   if (!(si->master_id= uint4korr(p))) 
  7.     si->master_id= server_id; 
  8.   si->thd= thd; 
  9.   pthread_mutex_lock(&LOCK_slave_list); 
  10.   unregister_slave(thd,0,0); //關(guān)鍵在這里,先取消注冊server_id相同的Slave線程 
  11.   res= my_hash_insert(&slave_list, (uchar*) si); //把新的Slave線程注冊到slave_list  //Vevb.com 
  12.   pthread_mutex_unlock(&LOCK_slave_list); 
  13.   return res; 
  14. ..... 

這是什么意思呢?這就是重連機制,slave_list是一個Hash表,server_id是Key,每一個線程注冊上來,需要刪掉同樣server_id的Slave線程,再把新的Slave線程加到slave_list表中.

線程注冊上來后,請求Binlog,發(fā)送COM_BINLOG_DUMP請求,Master會發(fā)送binlog給Slave,代碼如下:

  1. case COM_BINLOG_DUMP: 
  2.     { 
  3.       ulong pos; 
  4.       ushort flags; 
  5.       uint32 slave_server_id; 
  6.  
  7.       status_var_increment(thd->status_var.com_other); 
  8.       thd->enable_slow_log= opt_log_slow_admin_statements; 
  9.       if (check_global_access(thd, REPL_SLAVE_ACL)) 
  10.         break
  11.  
  12.       /* TODO: The following has to be changed to an 8 byte integer */ 
  13.       pos = uint4korr(packet); 
  14.       flags = uint2korr(packet + 4); 
  15.       thd->server_id=0; /* avoid suicide */ 
  16.       if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0 
  17.         kill_zombie_dump_threads(slave_server_id); 
  18.       thd->server_id = slave_server_id; 
  19.  
  20.       general_log_print(thd, command, "Log: '%s'  Pos: %ld", packet+10, 
  21.                       (long) pos); 
  22.       mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags); //不斷的發(fā)送日志給slave端 
  23.       unregister_slave(thd,1,1); //發(fā)送完成后清理Slave線程,因為執(zhí)行到這一步肯定是binlog dump線程被kill了 
  24.       /*  fake COM_QUIT -- if we get here, the thread needs to terminate */ 
  25.       error = TRUE; 
  26.       break
  27.     } 

mysql_binlog_send函數(shù)在sql_repl.cc,里面是輪詢Master binlog,發(fā)送給Slave,再來簡單看看unregister_slave做了什么,repl_failsafe.cc,代碼如下:

  1. void unregister_slave(THD* thd, bool only_mine, bool need_mutex) 
  2.   if (thd->server_id) 
  3.   { 
  4.     if (need_mutex) 
  5.       pthread_mutex_lock(&LOCK_slave_list); 
  6.  
  7.     SLAVE_INFO* old_si; 
  8.     if ((old_si = (SLAVE_INFO*)hash_search(&slave_list, 
  9.                                            (uchar*)&thd->server_id, 4)) && 
  10.         (!only_mine || old_si->thd == thd)) //拿到slave值 
  11.     hash_delete(&slave_list, (uchar*)old_si); //從slave_list中拿掉 
  12.  
  13.     if (need_mutex) 
  14.       pthread_mutex_unlock(&LOCK_slave_list); 
  15.   } 

這就可以解釋同樣的server_id為什么會被kill,因為一旦注冊上去,就會現(xiàn)刪除相同server_id的Slave線程,然后把當前的Slave加入,這是因為有時Slave斷開了,重新請求上來,當然需要踢掉原來的線程,這就是線程重連機制.

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 斗六市| 石泉县| 布拖县| 潜山县| 绵阳市| 夏河县| 邹平县| 华池县| 宝丰县| 晴隆县| 宜兰市| 新疆| 织金县| 江华| 桐梓县| 连州市| 松溪县| 喀喇沁旗| 吉木萨尔县| 吉安县| 延川县| 昭觉县| 临夏市| 潞城市| 岱山县| 闽侯县| 大冶市| 壤塘县| 赫章县| 钦州市| 扬州市| 舟山市| 叶城县| 洛扎县| 明溪县| 封开县| 揭东县| 昌邑市| 汝阳县| 漠河县| 永丰县|