mkdir -p /etc/mysql/certs && cd /etc/mysql/certs
# 1. 產生 CA
openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -subj "/CN=MySQL_CA" > ca-cert.pem
# 2. 產生 Server 憑證
openssl req -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -subj "/CN=mysql-master" > server-req.pem
openssl x509 -req -in server-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem
# 3. 產生 Client 憑證 (給從庫用)
openssl req -newkey rsa:2048 -days 3650 -nodes -keyout client-key.pem -subj "/CN=mysql-slave" > client-req.pem
openssl x509 -req -in client-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 02 -out client-cert.pem
# 4. 驗證
openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem
[mysqld]
ssl
ssl-ca=/etc/mysql/certs/ca-cert.pem
ssl-cert=/etc/mysql/certs/server-cert.pem
ssl-key=/etc/mysql/certs/server-key.pem
# 強制要求 SSL 連線 (可選,視相容性)
# require_secure_transport=ON
重啟 MySQL:`systemctl restart mysqld`
mysql> SHOW VARIABLES LIKE '%ssl%';
+---------------+----------------------------------+
| Variable_name | Value |
+---------------+----------------------------------+
| have_openssl | YES |
| have_ssl | YES |
| ssl_ca | /etc/mysql/certs/ca-cert.pem |
| ssl_cert | /etc/mysql/certs/server-cert.pem |
| ssl_key | /etc/mysql/certs/server-key.pem |
+---------------+----------------------------------+
將主庫產生的三個檔案複製到從庫對應目錄:
從庫 my.cnf:
[mysqld]
ssl
ssl-ca=/etc/mysql/certs/ca-cert.pem
ssl-cert=/etc/mysql/certs/client-cert.pem
ssl-key=/etc/mysql/certs/client-key.pem
重啟從庫 MySQL。
-- 主庫執行
CREATE USER 'repl_user'@'slave_ip' IDENTIFIED BY 'StrongPassword123!';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'slave_ip' REQUIRE SSL;
FLUSH PRIVILEGES;
[mysqld]
server-id = 1 -- 唯一,叢集內不可重複
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 7 -- 保留 7 天
max_binlog_size = 100M
binlog_format = ROW -- 推薦 ROW 格式,資料一致性最佳
binlog_do_db = your_database -- 僅同步指定庫 (可選)
# binlog_ignore_db = mysql,test,information_schema,performance_schema
重啟主庫。
# 主庫執行:--master-data=2 記錄 binlog 位置於檔案開頭 (CHANGE MASTER TO 註解)
mysqldump -u root -p --single-transaction --master-data=2 --databases your_database > /tmp/master_snapshot.sql
# 複製到從庫
scp /tmp/master_snapshot.sql slave_user@slave_ip:/tmp/
# 從庫執行
mysql -u root -p -e "CREATE DATABASE your_database;"
mysql -u root -p your_database < /tmp/master_snapshot.sql
head -n 50 /tmp/master_snapshot.sql | grep "CHANGE MASTER TO"
# 輸出範例:
# CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000072', MASTER_LOG_POS=898280714;
mysql> CHANGE MASTER TO
MASTER_HOST='master_ip',
MASTER_USER='repl_user',
MASTER_PASSWORD='StrongPassword123!',
MASTER_LOG_FILE='mysql-bin.000072',
MASTER_LOG_POS=898280714,
MASTER_SSL=1,
MASTER_SSL_CA='/etc/mysql/certs/ca-cert.pem',
MASTER_SSL_CERT='/etc/mysql/certs/client-cert.pem',
MASTER_SSL_KEY='/etc/mysql/certs/client-key.pem';
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: master_ip
Master_User: repl_user
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000072
Read_Master_Log_Pos: 898280714
Relay_Log_File: slave-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000072
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
Master_SSL_Allowed: Yes
Master_SSL_CA_File: /etc/mysql/certs/ca-cert.pem
Master_SSL_Cert: /etc/mysql/certs/client-cert.pem
Master_SSL_Key: /etc/mysql/certs/client-key.pem
關鍵指標:**Slave_IO_Running: Yes、Slave_SQL_Running: Yes、Seconds_Behind_Master: 0** 表示同步正常。
| 現象 | 原因 | 解決 |
|---|---|---|
| Slave_IO_Running: Connecting | 網路不通、SSL 憑證錯誤、帳密錯誤 | 1. telnet master 3306 2. mysql -h master -u repl_user -p --ssl-ca=... 測試 3. 檢查錯誤日誌 |
| Slave_SQL_Running: No | SQL 執行錯誤 (主鍵衝突、欄位不存在等) | 查看 Last_SQL_Error,手動修復後 `STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;` |
| Seconds_Behind_Master 持續增大 | 從庫執行緩慢、長查詢阻塞、單執行緒瓶頸 | 1. 檢查從庫慢查詢 2. 升級 MySQL 5.7+ 使用多執行緒複寫 (slave_parallel_workers) 3. 確保從庫硬體不低於主庫 |
| SSL 握手失敗 | CN 不匹配、憑證過期、CA 不信任 | openssl verify 檢驗;確認 server-cert CN 匹配 master_ip/hostname |
STOP SLAVE;
SET GLOBAL slave_parallel_workers = 4;
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';
START SLAVE;
[mysqld]
gtid_mode = ON
enforce_gtid_consistency = ON
log_slave_updates = 1
完成上述部署,即可實現跨資料中心、加密傳輸、高可用的 MySQL 主從架構,滿足異構應用讀寫分離與災備需求。