在生產環境中,我們的架構很多都是一主多從。比如一個主數據庫服務器M,兩個從數據庫服務器S1,S2同時指向主數據庫服務器M。當主服務器M因為意外情況宕機,需要將其中的一個從數據庫服務器(假設選擇S1)切換成主數據庫服務器,同時修改另一個從數據庫(S2)的配置,使其指向新的主數據庫(S1)。此外還需要通知應用修改主數據庫的IP地址,如果可能,將出現故障的主數據庫(M)修復或者重置成新的從數據庫。通常我們還有其他的方案來實現高可用,比如MHA,MySQL Cluster,MMM,這些將在后續的文章中慢慢道來。現在我們先看簡單的一主多從切換的情況。^_^
下面詳細介紹切換主從的操作步驟。
1.首先要確保所有的從數據庫都已經執行了relay log中的全部更新,在每個從庫上,執行stop slave io_thread,停止IO線程,然后檢查show processlist的輸出,直到看到狀態是Slave has read all relay log; waiting for the slave I/O thread to update it,表示更新都執行完畢
S1(從庫1操作):
mysql> stop slave io_thread; Query OK, 0 rows affected (0.06 sec) mysql> show processlist\G *************************** 1. row *************************** Id: 3 User: system user Host: db: NULL Command: Connect Time: 2601 State: Slave has read all relay log; waiting for the slave I/O thread to update it Info: NULL *************************** 2. row *************************** Id: 4 User: root Host: localhost db: NULL Command: Query Time: 0 State: NULL Info: show processlist 2 rows in set (0.00 sec) mysql>
S2(從庫2操作):
mysql> stop slave io_thread; Query OK, 0 rows affected (0.00 sec) mysql> show processlist\G *************************** 1. row *************************** Id: 4 User: system user Host: db: NULL Command: Connect Time: 2721 State: Slave has read all relay log; waiting for the slave I/O thread to update it Info: NULL *************************** 2. row *************************** Id: 5 User: root Host: localhost db: NULL Command: Query Time: 0 State: NULL Info: show processlist 2 rows in set (0.00 sec) mysql>
2.在從庫S1上,執行stop slave停止從服務,然后執行reset master以重置成主數據庫,並且進行授權賬號,讓S2(從庫2)有權限進行連接
S1(從庫1操作):
mysql> stop slave; Query OK, 0 rows affected (0.01 sec) mysql> reset master; Query OK, 0 rows affected (0.06 sec) mysql> grant replication slave on *.* to 'repl'@'192.168.0.100' identified by '123456'; Query OK, 0 rows affected (0.00 sec) mysql>
3.在S2(從庫2)上,執行stop slave停止從服務,然后執行change master to master_host='S1'以重新設置主數據庫,然后再執行start slave啟動復制:
S2(從庫2操作):
mysql> stop slave; Query OK, 0 rows affected (0.01 sec) mysql> change master to master_host='192.168.0.20'; Query OK, 0 rows affected (0.06 sec) mysql> start slave; Query OK, 0 rows affected (0.00 sec) mysql>
4.查看S2(從庫2)復制狀態是否正常:
mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.20 Master_User: repl Master_Port: 3306 Connect_Retry: 2 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 261 Relay_Log_File: MySQL-02-relay-bin.000002 Relay_Log_Pos: 407 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: yayun.% Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 261 Relay_Log_Space: 566 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 2 1 row in set (0.00 sec) mysql>
查看原來的從庫S1,現在的主庫的show processlist情況:
mysql> show processlist\G *************************** 1. row *************************** Id: 4 User: root Host: localhost db: NULL Command: Query Time: 0 State: NULL Info: show processlist *************************** 2. row *************************** Id: 7 User: repl Host: 192.168.0.100:60235 db: NULL Command: Binlog Dump Time: 184 State: Master has sent all binlog to slave; waiting for binlog to be updated Info: NULL 2 rows in set (0.00 sec) mysql>
5.通知所有的客戶端將應用指向S1(已提升為主庫),這樣客戶端發送的所有的更新變化將記錄到S1的二進制日志。
6.刪除S1(新的主庫)服務器上的master.info和relay-log.info文件,否則下次重啟時還會按照從庫啟動。我們也可以設置該參數:
skip_slave_start
7.最后,如果M服務器修復以后,則可以按照S2的方法配置成S1的從庫。
總結:
上面的測試步驟中S1默認都是打開log-bin選項的,這樣重置成主數據庫后可以將二進制日志記錄下來,並傳送到其他從庫,這是提升為主庫必須的。其次,S1沒有打開log-slave-updates參數,否則重置成主庫以后,可能會將已經執行過的二進制日志重復傳送給S2,導致S2同步錯誤。