日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql超大表处理方式是_第29问:MySQL 的复制心跳说它不想跳了

發(fā)布時間:2023/12/3 数据库 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql超大表处理方式是_第29问:MySQL 的复制心跳说它不想跳了 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

問題

最近年底,大家的數(shù)據(jù)庫經(jīng)常跑批量大事務(wù),會發(fā)現(xiàn)復(fù)制突然斷開,報錯“心跳與本地信息不兼容”:

會是什么原因?

實(shí)驗(yàn)

我們先來復(fù)現(xiàn)一下,再進(jìn)行分析。

寬油,做一對主從數(shù)據(jù)庫:

我們先造一個 500M 的空文件,下一步有用:

再制造一張大表,這里用到了之前的造表法,不同的是使用了一個 longblob 字段,讓少數(shù)的幾行記錄就能占用很大的 binlog 空間,方便我們后面做實(shí)驗(yàn)。

這里的 longblob 字段,用到了上一步我們做的空文件,

這樣我們獲得了一個行數(shù)較少,但體積很大的表。

現(xiàn)在起兩個會話,一個事務(wù)造表 t2,一個事務(wù)造表 t3,并同時提交操作,以下舉例其中一個事務(wù):

這樣就獲得了一個超大的 binlog,一共 32G,前 16G 是一個事務(wù),后 16G 是另一個事務(wù)。


小貼士
一個事務(wù)超過 binlog 的限制大小(最大 1G),就會在事務(wù)后直接切換到新的 binlog。
在同一個 binlog 中,我們想讓一個超大事務(wù)后再記錄一個事務(wù),所以讓兩個事務(wù)同時提交,放在同一個提交組中。


查看一下 master 上的 GTID,最后兩個事務(wù)分別是 25 和 26:

下面登錄到 slave上,開始表演:

我們先重置 GTID 和復(fù)制狀態(tài),然后騙 slave 說它已經(jīng)接到了 1-25 事務(wù),要從 26 號事務(wù)開始傳輸,也就是從 32G binlog 的中間位置開始傳輸。

然后開始復(fù)制的 IO 線程,過十幾秒,就可以看到復(fù)制報錯:

查看 Error log:

和我們想要復(fù)現(xiàn)的報錯一樣。

下面我們來看一下原理:

這個復(fù)現(xiàn)中有幾個要素:

  • 從報錯得知,報錯與心跳有關(guān),復(fù)制線必須配置復(fù)制心跳。
  • 一個 binlog 中包含兩個事務(wù),第一個事務(wù)超過 4G。(我們在復(fù)現(xiàn)中為了方便,將第二個事務(wù)也做成了大事務(wù),這一點(diǎn)不是必須的)。
  • 從大事務(wù)后的位置,開始進(jìn)行 binlog 復(fù)制傳輸。
  • 我們用 tcpdump 抓個包:

    用 wireshark 解開抓包,找到有問題的包(這里怎么找,我們分析后會有方法):

    我們來分析一下包結(jié)構(gòu),這里我們將包的內(nèi)容謄寫下來,方便大家閱讀:

    首先閱讀,https://dev.mysql.com/doc/internals/en/mysql-packet.html,了解 MySQL 的客戶端網(wǎng)絡(luò)包頭結(jié)構(gòu):

    將我們的包對應(yīng)上去:

    其后的一位 00,是 MySQL 的 command type(https://dev.mysql.com/doc/internals/en/command-phase.html),在此沒有意義,我們將其忽略,

    再繼續(xù)閱讀,https://dev.mysql.com/doc/internals/en/event-header-fields.html,了解 binlog event 的頭結(jié)構(gòu)如下:

    將我們的包對應(yīng)上去:

    接下來是個字符串,明顯是一個 binlog 的名字,最后四個字節(jié)(下圖中用黃色標(biāo)注)是 checksum,

    至此我們完成了一個心跳包的解析,并沒有看出嚴(yán)重的問題,不妨往前再找一個心跳包看看規(guī)律:

    我將重點(diǎn)在圖中標(biāo)注,就是 next_position 的位置,在這個包中為 0xfa000557,而其下一個包中為 0x19400583,明顯后面的 next_position 比前面的 next_position 小,這個不符合常理。

    而 MySQL 的報錯 heartbeat is not compatible with local info,也是在報這個問題:心跳包中的 position 不應(yīng)比當(dāng)前的 position 小。

    那是什么導(dǎo)致了這個問題,我們注意到 next_position 的字段長只有 4 字節(jié):

    也就是說,該字段最大值為 2 的 31 次方,也就是 4G,當(dāng)前 binlog 的位置大于 4G 時,該字段就會溢出。也就是說,之前我們看到的位置 0x19400583,實(shí)際丟掉了最高的一位,應(yīng)當(dāng)是 0x119400583。

    這也就導(dǎo)致了 binlog event 傳輸時,next_position 突然會變小,心跳機(jī)制會檢查到這個變化,產(chǎn)生報錯。

    那我們怎么解決這個問題?

    目前可能的方法有以下兩種:

  • 別用大事務(wù),別用大事務(wù),別用大事務(wù)。數(shù)據(jù)庫系統(tǒng)本來就不是為大事務(wù)設(shè)計的,總會踩到不少坑。
  • 停用心跳機(jī)制,這個問題并不是心跳機(jī)制帶來的問題,每個 binlog event 都會帶有這個包頭。只是心跳機(jī)制讓問題暴露了出來。如果關(guān)掉,提出問題的心跳機(jī)制,那么復(fù)制對于網(wǎng)絡(luò)故障就會不敏感,導(dǎo)致更大的問題。這種方式不推薦使用。
  • 復(fù)盤

    因?yàn)槲恼卤容^長,我們對邏輯進(jìn)行一下復(fù)盤:

  • 我們通過抓包分析,知道 binlog 傳輸?shù)木W(wǎng)絡(luò)包里,next_position 只有 4 個字節(jié),最大數(shù)值為 4G。
  • 我們在 master 上做了一個超過 4G 的大事務(wù),讓 slave 從這個大事務(wù)后開始傳輸。此時 master 會發(fā)送一個心跳包。
  • 心跳包中的 next_position 是 log event 在 binlog 位置,由于這個位置大于 4G,會被截斷,導(dǎo)致 next_position 比實(shí)際的小。
  • slave 收到心跳包,進(jìn)行檢測時發(fā)現(xiàn) next_position 比實(shí)際的小,進(jìn)行報錯。

    以上只是一種容易復(fù)現(xiàn)問題的場景。實(shí)際使用中,master 在一段時間不發(fā)送數(shù)據(jù)包后,或者特殊觸發(fā)條件,都會發(fā)送心跳包。

    對于一主多從的環(huán)境,每條復(fù)制鏈路的心跳是單獨(dú)發(fā)送的,也就會導(dǎo)致多個 slave 的表現(xiàn)會有所不同,有的 slave 會觸發(fā)報錯,有的 slave 由于 master 沒發(fā)送心跳包而不會觸發(fā)報錯。


    最后送上幾個小貼士:

    1)我們?nèi)绾慰焖僬业接袉栴}的包?

    報錯信息里已經(jīng)標(biāo)志了出錯的 log position 是 423626115,轉(zhuǎn)換成 16 進(jìn)制為:0x19400583,找到由此數(shù)據(jù)的包即可。

    2)一位一位讀包太麻煩了,怎么辦?

    好辦,先找到 server_id 的十六進(jìn)制形式,以此為基準(zhǔn)往后推定位數(shù)就可以。

    比如我們的 server_id 是 19327,很容易找到基準(zhǔn)位置。

    3)報錯里有一段亂碼是啥?

    最后這四位,是 MySQL 程序有缺陷,將包中的 checksum 作為文件名輸出了,對程序邏輯沒有影響。

    0x11 是 17,對應(yīng) ASCII 碼 "device control 1 character",鍵盤表達(dá)形式是 "ctrl + Q",打印形式就是 "^Q"。


    本文相關(guān)的 MySQL 的 bug 列表:

    https://bugs.mysql.com/bug.php?id=101948

    https://bugs.mysql.com/bug.php?id=101955


    關(guān)于 MySQL 技術(shù)內(nèi)容,你們還有什么想知道的嗎?趕緊****留言告訴小編吧!

    總結(jié)

    以上是生活随笔為你收集整理的mysql超大表处理方式是_第29问:MySQL 的复制心跳说它不想跳了的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。