本節說明如何在已上線且使用匿名交易的伺服器上啟用 GTID 交易,以及選擇性地啟用自動定位。此程序不需要將伺服器離線,適合在生產環境中使用。然而,如果您可以在啟用 GTID 交易時將伺服器離線,則該過程會更簡單。
您可以設定複寫通道,將 GTID 指派給尚未擁有任何 GTID 的複寫交易。此功能可以從不使用基於 GTID 的複寫的來源伺服器複寫到使用基於 GTID 的複寫的複本。如果可以在複寫來源伺服器上啟用 GTID(如此程序所述),請改用此方法。指派 GTID 是為無法啟用 GTID 的複寫來源伺服器設計的。如需此選項的詳細資訊,請參閱第 19.1.3.6 節,「從沒有 GTID 的來源複寫到有 GTID 的複本」。
開始之前,請確保所有伺服器上的gtid_mode
皆為OFF
。
下列程序可以隨時暫停,並在稍後從停止處繼續,或透過跳至第 19.1.4.3 節,「線上停用 GTID 交易」的對應步驟來反轉,這是停用 GTID 的線上程序。這使得程序具有容錯能力,因為在程序中間可能出現的任何不相關問題都可以像往常一樣處理,然後在停止處繼續程序。
若要啟用 GTID 交易,您必須先完成下列每個步驟,才能繼續下一個步驟。
在每部伺服器上,執行下列陳述式
SET @@GLOBAL.enforce_gtid_consistency = WARN;
讓伺服器使用您的正常工作負載執行一段時間,並監控日誌。如果此步驟在日誌中產生任何警告,請調整您的應用程式,使其僅使用與 GTID 相容的功能,且不產生任何警告。
在每部伺服器上,執行此陳述式
SET @@GLOBAL.enforce_gtid_consistency = ON;
在每部伺服器上,執行下列陳述式
SET @@GLOBAL.gtid_mode = OFF_PERMISSIVE;
伺服器執行此陳述式的順序沒有差異,但所有伺服器都必須在開始下一個步驟之前執行。
在每部伺服器上,執行下列陳述式
SET @@GLOBAL.gtid_mode = ON_PERMISSIVE;
如同前一個步驟,哪個伺服器先執行此語句並不重要,只要每個伺服器都在繼續下一步之前執行即可。
在每個伺服器上,等待直到
Ongoing_anonymous_transaction_count
為0
。 您可以使用SHOW STATUS
語句檢查其值,如下所示:mysql> SHOW STATUS LIKE 'Ongoing%'; +-------------------------------------+-------+ | Variable_name | Value | +-------------------------------------+-------+ | Ongoing_anonymous_transaction_count | 0 | +-------------------------------------+-------+ 1 row in set (0.00 sec)
在副本伺服器上,理論上可能出現此值為
0
然後又變為非零值的情況。這不是問題,只要它至少出現一次0
即可。等待所有在先前步驟中產生的交易複製到所有伺服器。 您可以在不停機更新的情況下執行此操作;重要的是,所有匿名交易都必須在繼續下一步之前完成複製。
請參閱 第 19.1.4.4 節,「驗證匿名交易的複製」,了解檢查所有匿名交易是否已複製到所有伺服器的一種方法。
如果您使用二進制日誌進行複製以外的任何操作,例如時間點備份和還原,請等待直到您不再需要包含沒有 GTID 的交易的舊二進制日誌。
例如,在所有交易都已複製後,您可以在執行備份的伺服器上執行
FLUSH LOGS
。 然後,明確地進行備份,或等待您可能已設定的任何定期備份程序的下一次迭代。理想情況下,您應該等待伺服器清除所有在完成上一步驟時存在的二進制日誌,以及等待在那之前進行的任何備份過期。
請記住,包含匿名交易(即沒有 GTID 的交易)的二進制日誌在下一步之後無法使用,在此之後,您必須確保沒有任何沒有 GTID 的交易在任何伺服器上保持未提交狀態。
在每部伺服器上,執行此陳述式
SET @@GLOBAL.GTID_MODE = ON;
在每個伺服器上,將
gtid-mode=ON
和enforce-gtid-consistency=ON
加入到my.cnf
。 這保證了 GTID 用於所有尚未處理的交易。為了開始使用 GTID 協定,以便您稍後執行自動故障轉移,請在每個副本伺服器上執行下一組語句。 如果您使用多來源複製,請為每個通道執行此操作,包括FOR CHANNEL
子句channel
STOP REPLICA [FOR CHANNEL 'channel']; CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION = 1 [FOR CHANNEL 'channel']; START REPLICA [FOR CHANNEL 'channel'];