| 角色 | OS | MySQL | IP | Server ID |
|---|---|---|---|---|
| Master | CentOS 7.6 | 5.7.35 (源碼編譯) | 192.168.1.22 | 1 |
| Slave | CentOS 7.6 | 5.7.35 (源碼編譯) | 192.168.1.33 | 2 |
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.33' IDENTIFIED BY 'repl_pass';
mysql> FLUSH PRIVILEGES;
安全建議:限制 Slave IP,生產環境強制 SSL:REQUIRE SSL
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog_format = ROW
gtid_mode = ON
enforce_gtid_consistency = ON
expire_logs_days = 7
max_binlog_size = 100M
# 可選:只同步特定庫
# binlog-do-db = business_db
關鍵:binlog_format=ROW 避免非確定性函數導致主從不一致;開啟 GTID 為後續故障切換鋪路。
# 啟動
mysqld_safe --user=mysql &
# 鎖表(阻塞寫入)
mysql> FLUSH TABLES WITH READ LOCK;
# 記錄 Binlog 位點
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 154 | | |
+------------------+----------+--------------+------------------+
# 另開終端備份
$ mysqldump --single-transaction --master-data=2 --all-databases > /backup/master_full_$(date +%F).sql
# 解鎖
mysql> UNLOCK TABLES;
[mysqld]
server-id = 2
log-bin = mysql-bin
relay_log = mysql-relay-bin
log-slave-updates = 1
read_only = 1
gtid_mode = ON
enforce_gtid_consistency = ON
# replicate-do-db = business_db
$ mysql -u root -p < /backup/master_full_2024-01-15.sql
mysql> CHANGE MASTER TO
MASTER_HOST='192.168.1.22',
MASTER_USER='repl',
MASTER_PASSWORD='repl_pass',
MASTER_AUTO_POSITION = 1; -- GTID 模式,無需手動指定 File/Pos
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.22
Master_User: repl
Master_Port: 3306
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 154
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 320
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
...
成功標誌:Slave_IO_Running: Yes + Slave_SQL_Running: Yes + Seconds_Behind_Master: 0
-- Master 執行
mysql> USE test; CREATE TABLE t_sync (id INT PRIMARY KEY, val VARCHAR(20));
mysql> INSERT INTO t_sync VALUES (1, 'from_master');
-- Slave 驗證
mysql> USE test; SELECT * FROM t_sync;
+----+--------------+
| id | val |
+----+--------------+
| 1 | from_master |
+----+--------------+
| 現象 | 原因 | 解決 |
|---|---|---|
| Slave_IO_Running: No / Connecting | 防火牆、賬號密碼、網絡不通 | telnet 3306、檢查 user 表、security group |
| The slave I/O thread stops because master and slave have equal MySQL server ids | server-id 重複 | 修改 my.cnf server-id 為唯一值,重啟 |
| Slave_SQL_Running: No / Errno 1062 | 主鍵衝突(Slave 有寫入) | STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE; |
| Seconds_Behind_Master: NULL | SQL 線程未運行 | 查看 Last_SQL_Error 修復後 START SLAVE |
-- Master
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS; -- 記錄 File, Pos
-- Slave
SELECT MASTER_POS_WAIT('mysql-bin.000001', 154); -- 等待追趕
-- Master
UNLOCK TABLES;
STOP SLAVE IO_THREAD;SHOW PROCESSLIST; 等待 State: Has read all relay logSTOP SLAVE;RESET MASTER;(清空本地 Binlog,重新開始)master.info、relay-log.info 防止重啟後仍以 Slave 身份啟動#!/bin/bash
# mysql_slave_monitor.sh
HOST=192.168.1.33
USER=monitor
PASS=xxx
STATUS=$(mysql -h$HOST -u$USER -p$PASS -e "SHOW SLAVE STATUS\G")
IO=$(echo "$STATUS" | grep Slave_IO_Running | awk '{print $2}')
SQL=$(echo "$STATUS" | grep Slave_SQL_Running | awk '{print $2}')
LAG=$(echo "$STATUS" | grep Seconds_Behind_Master | awk '{print $2}')
if [ "$IO" != "Yes" ] || [ "$SQL" != "Yes" ]; then
echo "CRITICAL: Slave threads down!" | mail -s "MySQL Slave Alert" admin@company.com
exit 2
elif [ "$LAG" -gt 300 ]; then
echo "WARNING: Slave lag ${LAG}s" | mail -s "MySQL Slave Lag" admin@company.com
exit 1
else
echo "OK: Slave healthy, lag ${LAG}s"
exit 0
fi
CentOS 下 MySQL 主從部署核心路徑:
GTID 模式 + ROW 格式 + server-id 唯一 + 專用賬號 + 自動化監控。
將「部署文檔化、變更腳本化、故障演練化」納入運維體系,才能在故障發生時從容應對。