萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

Shell 腳本實戰:自動修復 MySQL 主從複寫錯誤

場景痛點

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

部署步驟

  1. 儲存為 /usr/local/bin/fix_slave.sh,賦予執行權限:chmod +x /usr/local/bin/fix_slave.sh
  2. 建立日誌目錄:mkdir -p /var/log/mysql && chown mysql:mysql /var/log/mysql
  3. 加入 crontab -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,延遲過大時觸發告警而非單純跳過。
  • 記錄錯誤 SQL 到獨立審計表,方便事後追蹤補償。
copyright © 萬盛學電腦網 all rights reserved