MySQL主從同步機制與同步延時問題追查過程
前言
作為一名DBA,在工作中會經(jīng)常遇到一些MySQL主從同步延遲的問題,這些同步慢的問題,其實原因非常多,可能是因為主從的網(wǎng)絡(luò)問題導(dǎo)致,可能是因為網(wǎng)絡(luò)帶寬問題導(dǎo)致,可能是因為大事務(wù)導(dǎo)致,也可能是因為單線程復(fù)制導(dǎo)致的延遲。
今天遇到一個問題,Mysql持續(xù)報錯,主從同步延時數(shù)過大或錯誤。所以這篇文章給大家分享下主從同步的機制原理以及問題排查思路。
故障表現(xiàn)
最直觀的表現(xiàn)為:
mysql> show slave status\G; // 狀態(tài)一 Seconds_Behind_Master: NULL // 狀態(tài)二 Seconds_Behind_Master: 0 // 狀態(tài)三 Seconds_Behind_Master: 79
連續(xù)查詢,大部分時間該屬性值=0,偶發(fā)性出現(xiàn)Null或者79等延時值。導(dǎo)致觀察主從同步延時的監(jiān)控持續(xù)報警。
故障原因及解決方案
多臺備機的server-id一致,導(dǎo)致主機無法長時間同某一臺備機連接,進而無法正常同步。
修改server-id后,重啟數(shù)據(jù)庫恢復(fù)。
主從同步機制
MySQL的主從同步,又稱為復(fù)制(replication),是一種內(nèi)置的高可用高性能集群解決方案,主要功能有:
- 數(shù)據(jù)分布:同步不需要很大帶寬,可以實現(xiàn)多數(shù)據(jù)中心復(fù)制數(shù)據(jù)。
- 讀取的負載均衡:通過服務(wù)器集群,可以通過DNS輪詢、Linux LVS等GSLB(全局負載均衡)方式,降低主服務(wù)器的讀壓力。
- 數(shù)據(jù)庫備份:復(fù)制是備份的一部分,但并不能代替?zhèn)浞?。還需要與快照相結(jié)合。
- 高可用性和故障轉(zhuǎn)移:從服務(wù)器可以快速切換為主服務(wù)器,減少故障的停機時間和恢復(fù)時間。
主從同步分為3步:
- 主服務(wù)器(master)把數(shù)據(jù)更改記錄到二進制日志(binlog)中。
- 從服務(wù)器(slave)把主服務(wù)器的二進制日志復(fù)制到自己的中繼日志(relay log)中。
- 從服務(wù)器重做中繼日志中的日志,把更改應(yīng)用到自己的數(shù)據(jù)庫上,達到數(shù)據(jù)的一致性。
主從同步是一個異步實時的同步,會實時的傳輸,但存在執(zhí)行上的延時,如果主服務(wù)器壓力很大,延時也會相應(yīng)擴大。
通過上面的圖,可以看到一共需要3個線程:
- 主服務(wù)器的日志傳送線程:負責將二進制日志增量傳送到備機
- 從服務(wù)器的I/O線程:負責讀取主服務(wù)器的二進制日志,并保存為中繼日志
- 從服務(wù)器的SQL線程,負責執(zhí)行中繼日志
查看MySQL線程
我們可以使用show full processlist;
命令來查看MySQL的狀態(tài):
主機的狀態(tài):
備機的狀態(tài):
可以看到,我的集群架構(gòu)為1臺主機、4臺備機,所以在主機中有4個同步線程(已經(jīng)發(fā)送所有的binlog數(shù)據(jù)到備機,等待binlog日志更新),1個查看命令線程(show full processlist)。在備機中有1個查看命令線程,1個I/O線程(等待主機發(fā)送同步數(shù)據(jù)事件),1個SQL線程(已經(jīng)讀取了所有中繼日志,等待I/O線程來更新它)。
查看同步狀態(tài)
因為主從同步是異步實時的,也就是會存在延時的情況,我們可以通過show slave status;來查看備機上的同步延時:
在主從同步中我們需要關(guān)注的一些屬性,已經(jīng)給大家標紅了:
- Slave_IO_State: 當前I/O線程的狀態(tài)
- Master_Log_File: 當前同步的主服務(wù)器的二進制文件
- Read_Master_Log_Pos: 當前同步的主服務(wù)器的二進制文件的偏移量,單位為字節(jié),如圖中為已經(jīng)同步了12.9M(13630580/1024/1024)的內(nèi)容
- Relay_Master_Log_File: 當前中繼日志同步的二進制文件
- Slave_IO_Running: 從服務(wù)器中I/O線程的運行狀態(tài),YES為運行正常
- Slave_SQL_Running: 從服務(wù)器中SQL線程的運行狀態(tài),YES為運行正常
- Exec_Master_Log_Pos: 表示同步完成的主服務(wù)器的二進制日志偏移量
- Seconds_Behind_Master: 表示從服務(wù)器數(shù)據(jù)比主服務(wù)器落后的持續(xù)時長
同樣可以通過show master status;命令來查看主服務(wù)器的運行狀態(tài):
正常運行的主從同步狀態(tài):
Slave_IO_Running: YES
Slave_SQL_Running: YES
Seconds_Behind_Master: 0
問題排查
在理解了主從同步的機制后,再來看今天遇到的問題,通過查看備機狀態(tài),我們觀察在三種狀態(tài)下的幾個關(guān)鍵屬性值:
mysql> show slave status\G; #狀態(tài)一: Slave_IO_State: Reconnecting after a failed master event read Slave_IO_Running: No Slave_SQL_Running: Yes Seconds_Behind_Master: NULL #狀態(tài)二: Slave_IO_State: Waiting for master to send event Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0 #狀態(tài)三: Slave_IO_State: Queueing master event to the relay log Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 636
通過MySQL主從復(fù)制線程狀態(tài)轉(zhuǎn)變,我們可以看到三種狀態(tài)的不同含義:
# 狀態(tài)一 # 線程正嘗試重新連接主服務(wù)器,當連接重新建立后,狀態(tài)變?yōu)閃aiting for master to send event。 Reconnecting after a failed master event read # 狀態(tài)二 # 線程已經(jīng)連接上主服務(wù)器,正等待二進制日志事件到達。如果主服務(wù)器正空閑,會持續(xù)較長的時間。如果等待持續(xù)slave_read_timeout秒,則發(fā)生超時。此時,線程認為連接被中斷并企圖重新連接。 Waiting for master to send event # 狀態(tài)三 # 線程已經(jīng)讀取一個事件,正將它復(fù)制到中繼日志供SQL線程來處理。 Queueing master event to the relay log
在這里,我們可以猜測,由于某些原因,從服務(wù)器不斷的和主服務(wù)器進行斷開并嘗試重連,重連成功后又再次斷開。
我們再看看主機的運行情況:
發(fā)現(xiàn)問題出在10.144.63.*和10.144.68.*兩臺機器上,我們查看其中一臺的錯誤日志:
190214 11:33:20 [Note] Slave: received end packet from server, apparent master shutdown:
190214 11:33:20 [Note] Slave I/O thread: Failed reading log event, reconnecting to retry, log 'mysql-bin.005682' at postion 13628070
拿到關(guān)鍵字Slave: received end packet from server, apparent master shutdown: Google搜索一下,在文章Confusing MySQL Replication Error Message中可以看到原因為兩臺備機的server-id重復(fù)。
One day it happen to me, and took me almost an hour to find that out.
Moving foward I always use a base my.cnf to I copy to any other server and the first thing is to increase the server-id.
Could MySQL just use the servername intead of a numeric value?
問題修復(fù)
定位了問題,我們確認下是否重復(fù),發(fā)現(xiàn)兩臺備機的該字段確實相同:
vim my.cnf #replication log-bin=mysql-bin # 這個隨機數(shù)字相同導(dǎo)致的 server-id=177230069 sync_binlog=1
更改一個其他不同的數(shù)字,保存,重啟MySQL進程,報警恢復(fù)。
總結(jié)
最終來看,這個問題的解決非常簡單,但從剛開始的迷茫到最后的思路清晰,都是我們排查問題所常見的,這篇文章的主要收獲是讓你明白主從同步的機制和追查問題的思路,希望下次我們都能很快的解決主從同步帶給我們的問題。
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
參考資料
- 《MySQL基礎(chǔ)內(nèi)幕 InnoDB存儲引擎 第2版》P8.7 復(fù)制
- MySQL主從復(fù)制線程狀態(tài)轉(zhuǎn)變
- Confusing MySQL Replication Error Message
相關(guān)文章
解決Mysql?Binlog文件太大導(dǎo)致無法解析問題
這篇文章主要為大家介紹了解決Mysql?Binlog文件太大導(dǎo)致無法解析問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11MySQL優(yōu)化之表結(jié)構(gòu)優(yōu)化的5大建議(數(shù)據(jù)類型選擇講的很好)
很多人都將 數(shù)據(jù)庫設(shè)計范式 作為數(shù)據(jù)庫表結(jié)構(gòu)設(shè)計“圣經(jīng)”,認為只要按照這個范式需求設(shè)計,就能讓設(shè)計出來的表結(jié)構(gòu)足夠優(yōu)化,既能保證性能優(yōu)異同時還能滿足擴展性要求2014-03-03MySQL中TIMESTAMP類型返回日期時間數(shù)據(jù)中帶有T的解決
這篇文章主要介紹了MySQL中TIMESTAMP類型返回日期時間數(shù)據(jù)中帶有T的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12MySQL正則表達式regexp_replace函數(shù)的用法實例
regexp_replace的使用非常靈活,且容易忘記,故做此筆記,下面這篇文章主要給大家介紹了關(guān)于MySQL正則表達式regexp_replace函數(shù)的用法實例,需要的朋友可以參考下2022-09-09mysql 5.7.21 winx64綠色版安裝配置方法圖文教程
這篇文章主要為大家詳細介紹了mysql 5.7.21 winx64綠色版安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-09-09mysql如何將時間格式化為yyyy-MM-dd或yyyy-MM-dd?HH:mm:ss
這篇文章主要介紹了mysql如何將時間格式化為yyyy-MM-dd或yyyy-MM-dd?HH:mm:ss問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07批量清除128組節(jié)點db上面過期的binlog釋放磁盤空間實現(xiàn)思路
在 一臺db跳轉(zhuǎn)機上面, 寫一個腳本,訪問slave,遠程獲取正在復(fù)制的master上面的binlog位置, 然后再遠程去purge master上面的binlog2013-06-06