主從複製是 MySQL 高可用、讀寫分離、備份卸載的基石。本文涵蓋傳統文件/位置模式與 GTID 模式的完整配置、啟動驗證、雙向監控指標、常見故障 (IO/SQL 線程錯誤、數據不一致、主從切換) 處置 SOP,並提供 GTID 遷移路徑。
Server ID (全局唯一)、Binlog File + Position (傳統) 或 GTID (5.6+)。my.cnf[mysqld]
server-id = 1
log-bin = /var/log/mysql/mysql-bin
binlog_format = ROW
binlog-do-db = biz_db
binlog-ignore-db = mysql,sys,performance_schema,information_schema
sync_binlog = 1
expire_logs_days = 7
max_binlog_size = 100M
my.cnf[mysqld]
server-id = 2
log-bin = /var/log/mysql/mysql-bin # 從庫開啟 binlog 利於級聯/備份
relay-log = /var/log/mysql/relay-bin
read-only = 1 # 防誤寫
replicate-do-db = biz_db
replicate-ignore-db = mysql,sys,performance_schema,information_schema
master-info-repository = TABLE
relay-log-info-repository = TABLE
relay-log-recovery = ON # 崩潰自動修復 relay log
# Master
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.%' IDENTIFIED BY 'ReplPass123!';
FLUSH PRIVILEGES;
# Slave
CHANGE MASTER TO
MASTER_HOST='192.168.1.100',
MASTER_USER='repl',
MASTER_PASSWORD='ReplPass123!',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=1374,
MASTER_CONNECT_RETRY=60;
START SLAVE;
# Master/Slave 共同配置
gtid_mode = ON
enforce_gtid_consistency = ON
log-slave-updates = ON # Slave 也寫 binlog,級聯必需
# Slave 啟動 (無需指定文件/位置)
CHANGE MASTER TO
MASTER_HOST='192.168.1.100',
MASTER_USER='repl',
MASTER_PASSWORD='ReplPass123!',
MASTER_PORT=3306,
MASTER_AUTO_POSITION=1;
START SLAVE;
# Master
SHOW MASTER STATUS\G;
# 關鍵:File, Position, Binlog_Do_DB, Binlog_Ignore_DB
# Slave
SHOW SLAVE STATUS\G;
# 關鍵指標:
# Slave_IO_Running: Yes
# Slave_SQL_Running: Yes
# Seconds_Behind_Master: 0
# Master_Log_File / Read_Master_Log_Pos (傳統)
# Retrieved_Gtid_Set / Executed_Gtid_Set (GTID)
# Relay_Log_Space: Relay log 總大小
# Last_IO_Error / Last_SQL_Error: 最近錯誤
Seconds_Behind_Master > 300 (5 分鐘) → 告警Slave_IO_Running != Yes 或 Slave_SQL_Running != Yes → 緊急告警Relay_Log_Space > 10GB → 磁碟壓力告警Last_SQL_Error 非空 → 即時告警# 原因:從庫誤寫、主鍵衝突、外鍵失敗、非決定性函數
# 方案 A:跳過單條錯誤 (謹慎,確認數據可接受)
STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
START SLAVE;
# 方案 B:重新同步 (標準、安全)
# 1. Master 停寫 (或鎖表 FLUSH TABLES WITH READ LOCK)
# 2. Master 記錄位置: SHOW MASTER STATUS\G
# 3. mysqldump --single-transaction --master-data=2 biz_db > dump.sql
# 4. Slave 停止: STOP SLAVE; RESET SLAVE ALL;
# 5. Slave 導入: mysql biz_db < dump.sql
# 6. Slave 重新 CHANGE MASTER TO MASTER_AUTO_POSITION=1 (GTID) 或指定文件/位置
# 7. START SLAVE; 驗證 Seconds_Behind_Master=0
# 原因:網路斷開、認證失敗、Master binlog 被 purge、防火牆
# 排查:
SHOW SLAVE STATUS\G; -- 看 Last_IO_Error
# 常見錯誤碼:
# 1236: Master binlog 不存在 (已過期/被清理) -> 重新同步
# 1045: 認證失敗 -> 檢查用戶/密碼/Host
# 2003/2013: 網路不通 -> ping/telnet/防火牆/bind-address
# 修復:
# 1. 修復網路/認證
# 2. 若 Master binlog 仍在: CHANGE MASTER TO MASTER_LOG_FILE=..., MASTER_LOG_POS=...;
# 3. 若 Master binlog 已無: 重新同步 (方案 B)
# 4. START SLAVE;
# 工具校驗
pt-table-checksum --recurse=1 --databases=biz_db h=master,u=repl,p=pass
pt-table-checksum --recurse=1 --databases=biz_db h=slave,u=repl,p=pass
# 對比 CRC32 差異
# 修復
pt-table-sync --execute --print h=master,u=repl,p=pass h=slave,u=repl,p=pass
# 或指定表
pt-table-sync --execute h=master,u=repl,p=pass h=slave,u=repl,p=pass --tables=biz_db.orders
# 1. 確認 Slave 同步最新: Seconds_Behind_Master=0
# 2. Slave 停寫: SET GLOBAL read_only=ON; (已配置 read-only=1)
# 3. 應用層切換連接字符串指向新 Master (或 VIP 漂移)
# 5. 原 Master 恢復後作為新 Slave 接入 (重新同步)
# 6. 更新監控/備份/Proxy 配置
sync_binlog=1 + innodb_flush_log_at_trx_commit=1 零丟失。rpl_semi_sync_master=ON + rpl_semi_sync_slave=ON,至少一個 Slave 確認收到事務才提交,RPO=0。MASTER_DELAY=3600 Slave,防誤刪/誤更新 1 小時內閃回。mysqldump --single-transaction --master-data=2 不阻塞主庫。mysqld_exporter + Grafana 儀表板 + Alertmanager 告警。主從複製看似簡單,實則暗藏無數細節陷阱。標準化配置、GTID 全啟用、雙 1 安全、延遲從庫兜底、自動化監控與定期演練,構建起 MySQL 高可用的鋼鐵防線。