濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > MySQL如何生成唯一的server-id

MySQL如何生成唯一的server-id

熱門(mén)標(biāo)簽:福建外呼系統(tǒng)定制化 悟空科技電話機(jī)器人 騰訊地圖標(biāo)注提升 電銷(xiāo)卡外呼系統(tǒng)供應(yīng)商 銅陵防封電銷(xiāo)卡 怎么在地圖標(biāo)注位置生成圖片 真人語(yǔ)音電話機(jī)器人 400電話可以免費(fèi)申請(qǐng)嗎 美國(guó)反騷擾電話機(jī)器人

前言

我們都知道MySQL用server-id來(lái)唯一的標(biāo)識(shí)某個(gè)數(shù)據(jù)庫(kù)實(shí)例,并在鏈?zhǔn)交螂p主復(fù)制結(jié)構(gòu)中用它來(lái)避免sql語(yǔ)句的無(wú)限循環(huán)。這篇文章分享下我對(duì)server-id的理解,然后比較和權(quán)衡生成唯一server-id的幾種方式。

server_id的用途

簡(jiǎn)單說(shuō)來(lái),server_id有兩個(gè)用途:

1. 用來(lái)標(biāo)記binlog event的源產(chǎn)地,就是SQL語(yǔ)句最開(kāi)始源自于哪里。

2. 用于IO_thread對(duì)主庫(kù)binlog的過(guò)濾。如果沒(méi)有設(shè)置replicate-same-server-id=1,那么當(dāng)從庫(kù)的io_thread發(fā)現(xiàn)event的源與自己的server-id相同時(shí),就會(huì)跳過(guò)該event,不把該event寫(xiě)入到relay log中。從庫(kù)的sql_thread自然就不會(huì)執(zhí)行該event。這在鏈?zhǔn)交螂p主結(jié)構(gòu)中可以避免sql語(yǔ)句的無(wú)限循環(huán)。

注意:相同server-id的event在io_thread這一層就過(guò)濾了;而對(duì)于replicate-(do|ignore)-等規(guī)則,則是在sql_thread這一層過(guò)濾的。io_thread和sql_thread都有過(guò)濾的功能。

server_id為何不能重復(fù)

在同一個(gè)集群中,server-id一旦重復(fù),可能引發(fā)一些詭異問(wèn)題。

看看下面兩種情況:

圖1:主庫(kù)與從庫(kù)的server-id不同,但是兩個(gè)或多個(gè)從庫(kù)的server-id相同

這種情況下復(fù)制會(huì)左右搖擺。當(dāng)兩個(gè)從庫(kù)的server-id相同時(shí),如果從庫(kù)1已經(jīng)連接上主庫(kù),此時(shí)從庫(kù)2也需要連接到主庫(kù),發(fā)現(xiàn)之前有server-id相同的連接,就會(huì)先注銷(xiāo)該連接,然后重新注冊(cè)。

參考下面的代碼片段:

int register_slave(THD* thd, uchar* packet, uint packet_length)
{
 int res;
 SLAVE_INFO *si;
...
 if (!(si->master_id= uint4korr(p)))
 si->master_id= server_id;
 si->thd= thd;
 pthread_mutex_lock(LOCK_slave_list);
/* 先注銷(xiāo)相同server-id的連接*/
 unregister_slave(thd,0,0); 
/* 重新注冊(cè)*/
 res= my_hash_insert(slave_list, (uchar*) si);
 pthread_mutex_unlock(LOCK_slave_list);
 return res;
...
}

兩臺(tái)從庫(kù)不停的注冊(cè),不停的注銷(xiāo),會(huì)產(chǎn)生很多relay log文件,查看從庫(kù)狀態(tài)會(huì)看到relay log文件名不停改變,從庫(kù)的復(fù)制狀態(tài)一會(huì)是yes一會(huì)是正在連接中。

圖2:鏈?zhǔn)交螂p主結(jié)構(gòu)中,主庫(kù)與從庫(kù)的server-id相同

從庫(kù)1同時(shí)又是relay數(shù)據(jù)庫(kù),它能正確同步,然后把relay-log內(nèi)容重寫(xiě)到自己的binlog中。當(dāng)server-id為100的從庫(kù)2 io線程獲取binlog時(shí),發(fā)現(xiàn)所有內(nèi)容都是源自于自己,就會(huì)丟棄這些event。因此從庫(kù)2無(wú)法正確同步主庫(kù)的數(shù)據(jù)。只有直接寫(xiě)relay server的event能正確同步到從庫(kù)2。

上面兩種情況可以看到,在同一個(gè)replication set中,保持server-id的唯一性非常重要。

server_id的動(dòng)態(tài)修改

無(wú)意中發(fā)現(xiàn)server-id竟然是可以動(dòng)態(tài)修改的,可別高興的太早。好處是,上面圖1的情況下,直接修改其中一個(gè)從庫(kù)的server-id就可以解決server-id沖突的問(wèn)題。壞處很隱蔽,如下圖的結(jié)構(gòu):

現(xiàn)在假設(shè)active-master因?yàn)槟撤N原因與passive-master的同步斷開(kāi)后,passive-master上進(jìn)行了一些ddl變更。然后某dba突發(fā)奇想把passive-master的server-id修改為400。當(dāng)雙master的復(fù)制啟動(dòng)后,那些之前在passive-master上執(zhí)行的server-id為200的ddl變更,會(huì)從此陷入死循環(huán)。如果是alter table t engine=innodb,它會(huì)一直不停,可能你會(huì)發(fā)現(xiàn)。但是像update a=a+1;這樣的sql,你很難發(fā)現(xiàn)。當(dāng)然這種場(chǎng)景只是我的杜撰,這兒有個(gè)更真實(shí)的例子主備備的兩個(gè)備機(jī)轉(zhuǎn)為雙master時(shí)出現(xiàn)的詭異slave lag問(wèn)題:http://hatemysql.com/2010/10/15/主備備的兩個(gè)備機(jī)轉(zhuǎn)為雙master時(shí)出現(xiàn)的詭異slave-lag問(wèn)題/。

舉這兩個(gè)例子只是想說(shuō)明修改server-id有點(diǎn)危險(xiǎn),最好不要去修改,那么能一步到位生成它嗎?

生成唯一的server_id

常用的方法有如下幾種:

1. 采用隨機(jī)數(shù)

mysql的server-id是4字節(jié)整數(shù),范圍從0-4294967295,因此采用該范圍內(nèi)的隨機(jī)數(shù)來(lái)作為server-id產(chǎn)生沖突的可能性是非常小的。

2. 采用時(shí)間戳

直接用date +%s來(lái)生成server-id。一天86400秒來(lái)計(jì)算,往后計(jì)算50年,最大的server-id也才使用到86400*365*50,完全在server-id范圍內(nèi)。

3. 采用ip地址+端口

這是我們經(jīng)常采用的方法。例如ip為192.168.122.23,端口為3309,那么server-id可以寫(xiě)為122233309。產(chǎn)生沖突的可能性比較?。河龅?.*.122.23 或者*.*.12.223,而且搭建了同一個(gè)replication set的3309才會(huì)出現(xiàn)。

4. 采用集中的發(fā)號(hào)器

在管理服務(wù)器上采用自增的id來(lái)統(tǒng)一分配server-id。這可以保證不沖突,但是需要維護(hù)中心節(jié)點(diǎn)。

5. 分開(kāi)管理每個(gè)replication set

在每個(gè)replication set中為mysql庫(kù)增加一個(gè)管理表,保證每個(gè)從庫(kù)的server-id不沖突。

上面的幾種方法都不賴,但是:

  • 方法4加了維護(hù)負(fù)擔(dān),而且開(kāi)發(fā)環(huán)境、測(cè)試環(huán)境、線上環(huán)境都維護(hù)一套發(fā)號(hào)器的話,有點(diǎn)麻煩,混在一起又可能遇到網(wǎng)段隔離的風(fēng)險(xiǎn),還有發(fā)號(hào)器數(shù)據(jù)庫(kù)權(quán)限的問(wèn)題難于控制。所以不推薦。
  • 方法5實(shí)現(xiàn)了自治,但是管理成本有點(diǎn)高。從庫(kù)要能夠?qū)懼鲙?kù)的server-id表,復(fù)雜。
  • 5種方法都存在的問(wèn)題是,使用冷備的數(shù)據(jù)來(lái)擴(kuò)容,server-id需要手動(dòng)去修改,否則就與冷備源的server-id沖突。而且,當(dāng)mysql啟動(dòng)的時(shí)候,你無(wú)法判斷該mysql是剛通過(guò)備份擴(kuò)容的,還是之前一直正常運(yùn)行的。所以你不知道這個(gè)server-id到底要不要改。而我希望server-id對(duì)dba完全透明,又絕不產(chǎn)生沖突,即可徹底屏蔽這個(gè)討厭的東西。

建議的方法

其實(shí)很簡(jiǎn)單。ipv4是4字節(jié)的整數(shù),與server-id的范圍完全一樣。我們認(rèn)為只有ip地址+端口才能唯一的確定一個(gè)mysql實(shí)例,所以總是希望把ip信息和端口信息都集成到server-id中。但是別忘了,一個(gè)ip上不能同時(shí)啟動(dòng)兩個(gè)一樣的端口。所以,server-id只需采用ip地址的整數(shù)形式:select INET_ATON('192.168.12.45'),3232238637!所有新上線的實(shí)例,mysql啟動(dòng)腳本強(qiáng)制對(duì)server-id進(jìn)行檢查,發(fā)現(xiàn)server-id不對(duì)就進(jìn)行糾正,然后啟動(dòng)。這種方法有個(gè)前提條件:同一機(jī)器上的多個(gè)instance不要有主從關(guān)系,否則server-id一樣就會(huì)導(dǎo)致問(wèn)題。這種情況一般只會(huì)在測(cè)試環(huán)境出現(xiàn),在線上基本是沒(méi)有的。滿足了這個(gè)前提,所有問(wèn)題迎刃而解。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

您可能感興趣的文章:
  • MySQL主從同步中的server-id示例詳解

標(biāo)簽:臨汾 湖南 白銀 烏海 湖北 云浮 聊城 武威

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《MySQL如何生成唯一的server-id》,本文關(guān)鍵詞  MySQL,如何,生成,唯一,的,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《MySQL如何生成唯一的server-id》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于MySQL如何生成唯一的server-id的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    广元市| 庆云县| 察隅县| 额尔古纳市| 仙游县| 天台县| 连云港市| 大田县| 榆林市| 广平县| 河池市| 牡丹江市| 若尔盖县| 洪湖市| 夏河县| 宁安市| 临沭县| 隆回县| 化州市| 都江堰市| 长武县| 合水县| 潼南县| 行唐县| 平顺县| 南宫市| 甘德县| 扶绥县| 招远市| 永和县| 汽车| 安塞县| 弋阳县| 临安市| 咸宁市| 交城县| 莱西市| 阳东县| 岚皋县| 同心县| 仁寿县|