本文是對這篇文章MySQL InnoDB Cluster - Navigating the Cluster[1]的翻譯,翻譯如有不當的地方,敬請諒解,請尊重原創和翻譯勞動成果,轉載的時候請註明出處。謝謝! 當我們管理InnoDB Cluster時,一件非常重要的事情就是瞭解集群處於什麼樣的狀態,特別 ...
本文是對這篇文章MySQL InnoDB Cluster - Navigating the Cluster[1]的翻譯,翻譯如有不當的地方,敬請諒解,請尊重原創和翻譯勞動成果,轉載的時候請註明出處。謝謝!
當我們管理InnoDB Cluster時,一件非常重要的事情就是瞭解集群處於什麼樣的狀態,特別是要瞭解如何解釋集群狀態的報告,以及如何從各種具體失敗的故障場景中恢復。
組複製成員狀態
組成員所處的狀態取決於您是直接查詢該成員還是通過其他成員間接查詢該成員。
成員本身可見的狀態:
OFFLINE
RECOVERING
ERROR
ONLINE
對其他成員可見的狀態:
RECOVERING
UNREACHABLE
ONLINE
當MySQL實例正在運行但是其尚未加入任何組時,它就處於OFFLINE的狀態。一旦它加入一個組後,MySQL實例與該組的其它節點/成員同步數據時,它將切換為RECOVERING。一旦數據同步恢復完成(分散式恢復完成),它最終切換到ONLINE狀態. 如果數據同步由於某些原因失敗時,節點則會切換到ERROR狀態.
如果一個ONLINE的成員停止響應其他成員時(因為MySQL實例崩潰、網路問題、極高的負載、超時等),其狀態將切換為UNREACHABLE。如果該UNREACHABLE成員在超時之前沒有恢復,它將被其它成員從組中剔除/驅逐,因此在命令cluster.status()的輸出中狀態顯示為MISSING。驅逐成員的過程是通過投票完成的,因此只有在有足夠的成員並達到法定人數的情況下才會發生。
組或副本集狀態
下圖概述了組呈現的可能狀態以及狀態轉換是如何發生的。
實線過渡線顯示您可以在每種狀態下執行的 MySQL Shell 命令,而虛線則是在我們控制之外觸發的事件。
為了減少混亂,圖中省略了一些可能性。例如,只要有法定人數,您就可以在任何狀態下執行大多數命令,例如addInstance()或rejoinInstance()命令
cluster.status()命令顯示的組狀態信息:
OK –當所有成員都屬於ONLINE狀態並且有足夠的冗餘來容忍至少一個節點故障時顯示。
OK_PARTIAL –當一個或多個成員不可用,但仍有足夠的冗餘來容忍至少一個節點故障時。
OK_NO_TOLERANCE –當有足夠的ONLINE成員達到法定人數,但沒有冗餘節點時。兩個成員組成的團體沒有冗餘,因為如果其中一個成員變成了UNREACHABLE,另一個成員就無法單獨形成大多數;
這意味著您將遇到資料庫中斷(database outage)情況。但與單個成員組不同的是,至少您的數據在至少一個節點上仍然是安全的。
NO_QUORUM – 一個或多個成員可能仍然是ONLINE,但不能達到法定人數。在此狀態下,您的集群不能寫入,因此無法執行事務。但是,只讀查詢仍然可以執行,並且您的數據是完整且安全的。
UNKNOWN – 如果您從一個不是ONLINE或RECOVERING狀態的實例執行命令status()時,則會顯示此狀態。在這種情況下,請嘗試連接到其他成員。
UNAVAILABLE – 該狀態在圖中顯示,但不會出現在cluster.status()命令顯示中。在這種狀態下,該組的所有成員都是OFFLINE。他們可能仍在運行,但他們不再是該集群的一部分。例如,如果所有成員重新啟動而沒有重新加入集群,則可能會發生這種情況。
InnoDB集群的狀態轉換圖。(PDF版[2])
組分區
一種特殊場景是組分區,雖然這種情況很少見,但可能會造成混亂,有時甚至很危險,即組的成員實際上分為2個組或多個組。例如,如果您的成員位於不同的網路中並且他們之間的通信中斷,則可能會發生這種情況。在這種情況下,所有成員都是ONLINE,但一個組的成員將被另一個組成員視為UNREACHABLE,反之亦然。由於需要多數,只有一個組(最多一個組)能夠接收數據更新,從而保持資料庫的一致性。
但是,當使用cluster.forceQuorumUsingPartitionOf()命令時,就像下麵所解釋的那樣,您必須小心,不要讓組成員處於這種情況。如果遇到這種情況,您可能會創建2個單獨的組來分別接收更新,這將導致您的資料庫獨立處理事務並使其處於不一致的狀態。
5個成員全部ONLINE
5人成員分裂為兩組
從失敗中恢復
以下場景是發生故障時可能遇到的一些最常見情況。我們解釋瞭如何識別它們以及如何在MySQL Shell中使用InnoDB Cluster API 來恢復它們。
伺服器重新啟動
如果mysqld 由於任何原因(實例崩潰、預期重啟、重新配置等)重新啟動,那麼當它恢復時,它將不再位於該組/集群中。它需要重新加入它,這在某些情況下可能必須手動完成。為此,您可以使用cluster.rejoinInstance()命令將MySQL實例加入回組中。它用的參數是MySQL實例的URI。
示例:
cluster.rejoinInstance("[email protected]")
失去法定人數
如果副本集的大量成員變成UNREACHABLE,以至於它不再擁有多數成員,則它將不再擁有法定人數,並且無法對任何更改做出決定。這包括用戶事務,還包括組拓撲的更改。這意味著,即使成員從UNREACHABLE狀態恢復了, 該成員依然被阻止,無法重新加入該群組。
要從這種情況中恢復,我們必須首先取消該組(unblock the group),方法是將其重新配置,僅考慮當前ONLINE的成員並忽略所有其他成員。為此,用cluster.forceQuorumUsingPartitionOf()這個命令 傳入複製集中中一個ONLINE的成員的URL作為參數。所有可見的ONLINE成員都將添加到重新定義的組中。
請註意,這個命令是一個危險的命令。如上所述,如果您的組中碰巧有一個分區,您可能會意外地出現裂腦,這將導致資料庫不一致。在使用此命令之前,請確保所有成員都是UNREACHABLE,並且狀態為OFFLINE。
例子: cluster.forceQuorumUsingPartitionOf("[email protected]")
所有成員OFFLINE
cluster.forceQuorumUsingPartitionOf()命令要求至少有一個實例一直處於ONLINE並且屬於該組。如果不知何故,您的所有成員都是OFFLINE狀態,則只有從單個種子成員中再次“引導”該組,您才能恢復該組。要執行此操作,您需要在選中的種子實例上使用命令dba.restoreFromCompleteOutage(),然後在剩餘成員上使用命令rejoinInstance(),直到集群完全恢復為止。
註意:此命令從 MySQL Shell 1.0.7 開始可用。
結論
MySQL InnoDB Cluster意在為擁有不同知識和經驗水平的 MySQL 用戶提供高可用性。雖然cluster.status()命令可以讓您一目瞭然地監控集群的狀態,但如何瞭解原理非常重要,這樣您就知道何時需要該採取哪些措施來確保 MySQL 資料庫保持最佳運行狀態。
參考資料
1: https://dev.mysql.com/blog-archive/mysql-innodb-cluster-navigating-the-cluster/,
[2]pdf: https://dev.mysql.com/blog-archive/mysqlserverteam/wp-content/uploads/2016/12/AvailabilityStateMachine.pdf