
我們的資料中心停電後,從屬 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 處理過的命令。
答案1
我選擇了第一個選擇。
直到從屬設備開始嘗試執行與主鍵衝突的插入操作為止。如前所述,從站完成的工作比主站二進位日誌所保留的工作還要多。我沒有預料到的一個方面是從屬設備包含主設備中沒有的資料;即從設備在主設備斷電之前保留了一些事務沒有堅持下來了。
由於就我而言,這些交易與付款無關或類似,因此我選擇從從屬伺服器中刪除資料(從而丟失一些已發生但主伺服器中不存在的資料),然後讓複製再次運行。這使奴隸們完全跟上時代的腳步。如果資料更重要,我們有足夠的自動增量偏移量來為我們手動調整資料並確保引用完整性不會受到損害提供一些迴旋餘地。值得慶幸的是,在這種情況下我們不需要這樣做。
對於處於這種困境的(被動)主-主配置的機器,我選擇了類似的方法。透過被動主控,我的意思是我們有一個主動主控(伺服器A),它是所有寫入作業的所在,還有一個被動主控(伺服器B),它允許在零停機時間內進行架構更新。儘管知道這意味著我們丟失了一些不重要的持久事務,但仍選擇活動主伺服器(伺服器 A)中的資料作為真實值。
更改了從站上的日誌檔案和位置。
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) 上不存在於伺服器 A 的主伺服器中的資料列。
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.
答案2
這取決於從屬設備是主設備的精確複製品的重要性。你的第一個選擇在某種程度上會起作用,但奴隸很可能會失去主人的資訊。如果您可以忍受這一點,因為數據是瞬態的或其他原因,那麼就去做吧。如果從屬伺服器是正確的副本很重要,那麼第二個選項可能是您唯一的選擇。不幸的是,MySQL 複製不會善待任何類型的意外中斷,我發現此類問題比我在複製架構中希望的要頻繁得多。