Mysql
斷電後的 MySQL 複製問題
在我們的數據中心停電後,從屬 MySQL 數據庫正在苦苦掙扎。
這是其中一位奴隸的日誌:
100118 10:05:56 [Note] Slave I/O thread: connected to master 'repl@db1:3306', replication started in log 'bin-log.004712' at position 724207814 100118 10:05:56 [ERROR] Error reading packet from server: Client requested master to start replication from impossible position ( server_errno=1236) 100118 10:05:56 [ERROR] Got fatal error 1236: 'Client requested master to start replication from impossible position' from master when reading data from binary log 100118 10:05:56 [Note] Slave I/O thread exiting, read up to log 'bin-log.004712', position 724207814
控制台顯示了更多細節:
mysql> show slave status \G; *************************** 1. row *************************** Slave_IO_State: Master_Host: db1 Master_User: repl Master_Port: 3306 Connect_Retry: 10 Master_Log_File: bin-log.004712 Read_Master_Log_Pos: 724207814 Relay_Log_File: mysqld-relay-bin.000105 Relay_Log_Pos: 98 Relay_Master_Log_File: bin-log.004712 Slave_IO_Running: No Slave_SQL_Running: Yes Replicate_Do_DB: mmplive1,mmpjcr,fui Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 724207814 Relay_Log_Space: 98 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: NULL 1 row in set (0.00 sec) ERROR: No query specified
查看 master 上的 bin 日誌,我們有:
-rw-rw---- 1 mysql mysql 724200412 Jan 18 09:22 bin-log.004712 -rw-rw---- 1 mysql mysql 1904 Jan 18 09:27 bin-log.index -rw-rw---- 1 mysql mysql 5046830 Jan 18 11:22 slow-log -rw-rw---- 1 mysql mysql 198249613 Jan 18 11:24 bin-log.004713
- Slave 狀態顯示 Exec_Master_Log_Pos 和 Read_Master_Log_Pos 都是 724207814,對於當時的二進制日誌 bin-log.004712。據我了解,這個值是二進制日誌文件中的字節位置。
- 該 bin-log.004712 文件只有 724200412 字節,因此從站認為他們完成的工作比實際保存在文件中的工作多 7402 字節(位於 ext3 fs、RAID-10、RHEL5 上)。因此有關不可能的日誌位置等的錯誤消息。
修復奴隸的最佳方法是什麼?
我正在考慮的選項:
- 將每個從站設置為指向下一個 bin-log 文件 (bin-log.004713) 中的位置 0 並讓它們離開,但我不確定這有多安全,或者可能會失去多少數據。
- 我是否需要進行完整備份和恢復(由於 InnoDB 表上的表鎖定而假定相關的停機時間)?如果可能的話,我想避免這種情況。
更新:
我錯過了另一個選擇:將每個從屬執行位置向後一點,以便它嘗試複製它已經從 bin-log.004712 處理的命令。
我選擇了第一個選項。
這一直到從站開始嘗試進行與主鍵衝突的插入。如前所述,slave 所做的工作比 master bin-log 所堅持的要多。我沒有預料到的一個方面是,slave 包含的數據不在 master 中。即從屬伺服器在主伺服器沒有持續的斷電之前堅持了一些事務。
因為就我而言,這些交易與付款無關或類似,我選擇從從屬伺服器中刪除數據(從而失去一些已經發生但在主伺服器中不存在的數據),然後讓複製再次執行. 這使奴隸完全與時俱進。如果數據更重要,我們有足夠的自動增量偏移量給我們一些迴旋餘地來手動處理數據並確保引用完整性不受影響。幸運的是,在這種情況下我們不需要這樣做。
對於處於這種困境的(被動)主主配置的機器,我選擇了類似的方法。被動主控,我的意思是我們有一個主動主控(serverA),它是所有寫入的地方,還有一個被動主控(serverB),它允許在零停機時間的情況下進行模式更新。活動主伺服器(serverA)中的數據被選為真實值,儘管我們知道這意味著我們失去了一些被認為不重要的持久事務。
- 更改了從站上的日誌文件和位置。
CHANGE MASTER MASTER_LOG_FILE='bin-log.004713', MASTER_LOG_POS=0; -- on serverB
- 重新啟動被動主機(serverB)上的從屬複製,直到它因違反主鍵約束而失敗,與其他從屬一樣。
START SLAVE; -- on serverB
- 停止從被動主機 (serverB) 到主動主機 (serverA) 的從屬複製。
STOP SLAVE; -- on serverA
- 刪除從伺服器 (serverB) 上的行,這些行在 serverA 上的主伺服器中不存在。
DELETE FROM SOME_TABLE WHERE ID IN (???,????); -- on serverB SHOW MASTER STATUS\G; -- get the new master log position on serverB
- 移動主動主 (serverA) 從屬執行位置以跳過從被動主 (serverB) 中刪除的那些。
CHANGE MASTER TO MASTER_LOG_POS=???; --on serverA; use the value just obtained from serverB
- 在主動主伺服器 (serverA) 和被動主伺服器上重新啟動複製。
START SLAVE; -- on both machines. serverA does nothing and serverB starts catching up.