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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

php 判断心跳包报错,第29问:MySQL 的复制心跳说它不想跳了

發布時間:2023/12/10 数据库 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php 判断心跳包报错,第29问:MySQL 的复制心跳说它不想跳了 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題

最近年末,你們的數據庫常常跑批量大事務,會發現復制忽然斷開,報錯“心跳與本地信息不兼容”: 會是什么緣由?php

實驗

咱們先來復現一下,再進行分析。html

寬油,作一對主從數據庫:

mysql

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

再制造一張大表,這里用到了以前的造表法,不一樣的是使用了一個 longblob 字段,讓少數的幾行記錄就能占用很大的 binlog 空間,方便咱們后面作實驗。數據庫

這里的 longblob 字段,用到了上一步咱們作的空文件, 網絡

這樣咱們得到了一個行數較少,但體積很大的表。tcp

如今起兩個會話,一個事務造表 t2,一個事務造表 t3,并同時提交操做,如下舉例其中一個事務: spa

這樣就得到了一個超大的 binlog,一共 32G,前 16G 是一個事務,后 16G 是另外一個事務。 線程

小貼士

一個事務超過 binlog 的限制大小(最大 1G),就會在事務后直接切換到新的 binlog。設計

在同一個 binlog 中,咱們想讓一個超大事務后再記錄一個事務,因此讓兩個事務同時提交,放在同一個提交組中。

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

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

咱們先重置 GTID 和復制狀態,而后騙 slave 說它已經接到了 1-25 事務,要從 26 號事務開始傳輸,也就是從 32G binlog 的中間位置開始傳輸。

而后開始復制的 IO 線程,過十幾秒,就能夠看到復制報錯:

查看 Error log:

和咱們想要復現的報錯同樣。

下面咱們來看一下原理:

這個復現中有幾個要素:

從報錯得知,報錯與心跳有關,復制線必須配置復制心跳。

一個 binlog 中包含兩個事務,第一個事務超過 4G。(咱們在復現中為了方便,將第二個事務也作成了大事務,這一點不是必須的)。

從大事務后的位置,開始進行 binlog 復制傳輸。

咱們用 tcpdump 抓個包:

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

咱們來分析一下包結構,這里咱們將包的內容謄寫下來,方便你們閱讀:

將咱們的包對應上去:

將咱們的包對應上去:

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

至此咱們完成了一個心跳包的解析,并無看出嚴重的問題,不妨往前再找一個心跳包看看規律:

我將重點在圖中標注,就是 next\_position 的位置,在這個包中為 0xfa000557,而其下一個包中為 0x19400583,明顯后面的 next\_position 比前面的 next_position 小,這個不符合常理。

而 MySQL 的報錯 heartbeat is not compatible with local info,也是在報這個問題:心跳包中的 position 不該比當前的 position 小。

那是什么致使了這個問題,咱們注意到 next_position 的字段長只有 4 字節:

也就是說,該字段最大值為 2 的 31 次方,也就是 4G,當前 binlog 的位置大于 4G 時,該字段就會溢出。也就是說,以前咱們看到的位置 0x19400583,實際丟掉了最高的一位,應當是 0x119400583。

這也就致使了 binlog event 傳輸時,next_position 忽然會變小,心跳機制會檢查到這個變化,產生報錯。

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

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

別用大事務,別用大事務,別用大事務。數據庫系統原本就不是為大事務設計的,總會踩到很多坑。

停用心跳機制,這個問題并非心跳機制帶來的問題,每一個 binlog event 都會帶有這個包頭。只是心跳機制讓問題暴露了出來。若是關掉,提出問題的心跳機制,那么復制對于網絡故障就會不敏感,致使更大的問題。這種方式不推薦使用。

復盤

由于文章比較長,咱們對邏輯進行一下復盤:

咱們經過抓包分析,知道 binlog 傳輸的網絡包里,next_position 只有 4 個字節,最大數值為 4G。

咱們在 master 上作了一個超過 4G 的大事務,讓 slave 從這個大事務后開始傳輸。此時 master 會發送一個心跳包。

心跳包中的 next\_position 是 log event 在 binlog 位置,因為這個位置大于 4G,會被截斷,致使 next\_position 比實際的小。

slave 收到心跳包,進行檢測時發現 next_position 比實際的小,進行報錯。

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

對于一主多從的環境,每條復制鏈路的心跳是單獨發送的,也就會致使多個 slave 的表現會有所不一樣,有的 slave 會觸發報錯,有的 slave 因為 master 沒發送心跳包而不會觸發報錯。

最后送上幾個小貼士

1)咱們如何快速找到有問題的包?

報錯信息里已經標志了出錯的 log position 是 423626115,轉換成 16 進制為:0x19400583,找到由此數據的包便可。

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

好辦,先找到 server_id 的十六進制形式,以此為基準日后推定位數就能夠。

好比咱們的 server_id 是 19327,很容易找到基準位置。

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

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

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

本文相關的 MySQL 的 bug 列表:

關于 MySQL 的技術內容,大家還有什么想知道的嗎?趕忙留言告訴小編吧!

總結

以上是生活随笔為你收集整理的php 判断心跳包报错,第29问:MySQL 的复制心跳说它不想跳了的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。