MySQL 主從複寫中,Slave 的 SQL 執行緒常因主鍵衝突、外鍵約束、暫時性網路抖動等報錯停止。手動處理 STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE; 既繁瑣又易遺漏。下方腳本可定時檢測並自動跳過單條錯誤事務,讓複寫自我恢復。
#!/bin/bash
# ==========================================
# MySQL Slave 自動錯誤修復腳本
# 功能:檢測 Slave_IO_Running / Slave_SQL_Running 狀態
# 若任一為 No,自動跳過 1 筆錯誤事務並重啟複寫
# 部署:放入 /usr/local/bin/fix_slave.sh,加入 crontab 每分鐘執行
# ==========================================
# ---- 配置區(請根據實際環境修改) ----
MYSQL_CMD="/usr/local/mysql/bin/mysql"
MYSQL_USER="root"
MYSQL_PASS="your_strong_password"
MYSQL_SOCK="/tmp/mysql.sock"
LOG_FILE="/var/log/mysql/fix_slave.log"
INTERFACE="eth0" # 取得本機 IP 用
# -------------------------------------
DATETIME=$(date "+%Y-%m-%d %H:%M:%S")
SLAVE_IP=$(ifconfig "$INTERFACE" | grep "inet " | awk '{print $2}')
# 獲取最新狀態寫入臨時日誌(避免直接管道讀取不穩定)
"$MYSQL_CMD" -u"$MYSQL_USER" -p"$MYSQL_PASS" -S "$MYSQL_SOCK" -e "SHOW SLAVE STATUS\G" > "$LOG_FILE" 2>&1
IO_RUNNING=$(grep "Slave_IO_Running:" "$LOG_FILE" | awk '{print $2}')
SQL_RUNNING=$(grep "Slave_SQL_Running:" "$LOG_FILE" | awk '{print $2}')
if [[ "$IO_RUNNING" == "Yes" && "$SQL_RUNNING" == "Yes" ]]; then
echo "[$DATETIME] $SLAVE_IP Slave 運行正常" >> "$LOG_FILE"
exit 0
fi
# 任一異常 → 記錄並嘗試修復
echo "[$DATETIME] $SLAVE_IP Slave 異常 (IO:$IO_RUNNING, SQL:$SQL_RUNNING),嘗試自動修復" >> "$LOG_FILE"
"$MYSQL_CMD" -u"$MYSQL_USER" -p"$MYSQL_PASS" -S "$MYSQL_SOCK" <<EOF
STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
START SLAVE;
EOF
# 再次檢查結果
sleep 2
"$MYSQL_CMD" -u"$MYSQL_USER" -p"$MYSQL_PASS" -S "$MYSQL_SOCK" -e "SHOW SLAVE STATUS\G" > "$LOG_FILE" 2>&1
IO_RUNNING=$(grep "Slave_IO_Running:" "$LOG_FILE" | awk '{print $2}')
SQL_RUNNING=$(grep "Slave_SQL_Running:" "$LOG_FILE" | awk '{print $2}')
if [[ "$IO_RUNNING" == "Yes" && "$SQL_RUNNING" == "Yes" ]]; then
echo "[$DATETIME] $SLAVE_IP 修復成功,複寫已恢復" >> "$LOG_FILE"
else
echo "[$DATETIME] $SLAVE_IP 修復失敗,請人工介入 (IO:$IO_RUNNING, SQL:$SQL_RUNNING)" >> "$LOG_FILE"
# 這裡可加入告警:發送郵件、釘釘、企業微信等
fi
/usr/local/bin/fix_slave.sh,賦予執行權限:chmod +x /usr/local/bin/fix_slave.shmkdir -p /var/log/mysql && chown mysql:mysql /var/log/mysqlcrontab -e:* * * * * /usr/local/bin/fix_slave.sh >/dev/null 2>&1| 變數 | 說明 |
|---|---|
SQL_SLAVE_SKIP_COUNTER = 1 | 跳過 1 個導致錯誤的事務(事件)。若錯誤事務包含多條語句,可能需多次執行。 |
STOP SLAVE / START SLAVE | 必須先停止複寫執行緒才能修改計數器。 |
| 日誌輪轉 | 建議配合 logrotate 管理 /var/log/mysql/fix_slave.log,避免佔滿磁碟。 |
自動跳過事務意味著資料可能不一致!
SHOW SLAVE STATUS\G 中的 Last_SQL_Error),修正主庫資料或手動補齊後再恢複寫。pt-slave-restart (Percona Toolkit) 實現更健壯的自動恢復與監控。Seconds_Behind_Master,延遲過大時觸發告警而非單純跳過。