🔄 MySQL 主从复制

高可用架构 - 主从复制配置、管理与监控

主从复制概述

MySQL 主从复制是一种数据同步技术,通过将主服务器(Master)的数据变更自动复制到一个或多个从服务器(Slave),实现数据的高可用性、读写分离和负载均衡。

🎯 异步复制

主服务器不等待从服务器确认,性能最好但可能丢失数据

⚡ 半同步复制

主服务器等待至少一个从服务器确认,平衡性能和安全性

🔒 同步复制

主服务器等待所有从服务器确认,最安全但性能较低

📊 基于语句复制

复制 SQL 语句,日志文件小但可能不一致

📝 基于行复制

复制数据行变更,确保一致性但日志文件大

🔄 混合复制

自动选择最优复制方式,兼顾性能和一致性

主从复制架构图

主服务器 (Master)
从服务器 1 (Slave)

从服务器 2 (Slave)

从服务器 3 (Slave)

数据流向:主服务器 → 二进制日志 → 从服务器中继日志 → 从服务器数据

主从复制的优势:
  • 高可用性:主服务器故障时可快速切换到从服务器
  • 读写分离:主服务器处理写操作,从服务器处理读操作
  • 负载均衡:分散读取负载到多个从服务器
  • 数据备份:从服务器作为实时数据备份
  • 数据分析:在从服务器上进行报表和分析,不影响主服务器性能
  • 地理分布:在不同地理位置部署从服务器,提高访问速度

主从复制配置

准备测试环境

-- 创建复制测试数据库 CREATE DATABASE replication_demo; USE replication_demo; -- 创建测试表 CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, email VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); CREATE TABLE orders ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, order_number VARCHAR(50) NOT NULL UNIQUE, total_amount DECIMAL(10,2) NOT NULL, status ENUM('pending', 'paid', 'shipped', 'delivered') DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ); -- 插入测试数据 INSERT INTO users (username, email) VALUES ('alice', 'alice@example.com'), ('bob', 'bob@example.com'), ('charlie', 'charlie@example.com'); INSERT INTO orders (user_id, order_number, total_amount, status) VALUES (1, 'ORD-001', 99.99, 'paid'), (2, 'ORD-002', 149.99, 'shipped'), (3, 'ORD-003', 79.99, 'pending'); SELECT 'Test data created successfully' AS message;

主服务器配置

1. 修改主服务器配置文件 (my.cnf)

# /etc/mysql/my.cnf 或 /etc/my.cnf [mysqld] # 服务器唯一标识 server-id = 1 # 启用二进制日志 log-bin = mysql-bin binlog-format = ROW # 推荐使用 ROW 格式 # 二进制日志过期时间(天) expire-logs-days = 7 # 二进制日志文件大小 max-binlog-size = 100M # 同步二进制日志到磁盘 sync-binlog = 1 # 指定要复制的数据库(可选) # binlog-do-db = replication_demo # 指定不复制的数据库(可选) # binlog-ignore-db = mysql # binlog-ignore-db = information_schema # binlog-ignore-db = performance_schema # binlog-ignore-db = sys # InnoDB 设置 innodb-flush-log-at-trx-commit = 1 innodb-support-xa = 1 # 半同步复制插件(可选) # plugin-load = "rpl_semi_sync_master=semisync_master.so" # rpl-semi-sync-master-enabled = 1 # rpl-semi-sync-master-timeout = 1000
-- 2. 重启 MySQL 服务 -- sudo systemctl restart mysql -- 3. 创建复制用户 CREATE USER 'replication_user'@'%' IDENTIFIED BY 'strong_password'; GRANT REPLICATION SLAVE ON *.* TO 'replication_user'@'%'; FLUSH PRIVILEGES; -- 4. 查看主服务器状态 SHOW MASTER STATUS; -- 记录输出结果,例如: -- +------------------+----------+--------------+------------------+ -- | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | -- +------------------+----------+--------------+------------------+ -- | mysql-bin.000001 | 154 | | | -- +------------------+----------+--------------+------------------+ -- 5. 锁定表(可选,用于一致性备份) -- FLUSH TABLES WITH READ LOCK; -- 6. 备份主服务器数据 -- mysqldump -u root -p --all-databases --master-data=2 > master_backup.sql -- 7. 解锁表 -- UNLOCK TABLES; -- 查看二进制日志文件 SHOW BINARY LOGS; -- 查看二进制日志事件 SHOW BINLOG EVENTS IN 'mysql-bin.000001' LIMIT 10;

从服务器配置

1. 修改从服务器配置文件 (my.cnf)

# /etc/mysql/my.cnf 或 /etc/my.cnf [mysqld] # 服务器唯一标识(必须与主服务器不同) server-id = 2 # 启用中继日志 relay-log = mysql-relay-bin # 从服务器只读(推荐) read-only = 1 # 超级用户可以在只读模式下写入 super-read-only = 0 # 指定要复制的数据库(可选) # replicate-do-db = replication_demo # 指定不复制的数据库(可选) # replicate-ignore-db = mysql # replicate-ignore-db = information_schema # replicate-ignore-db = performance_schema # replicate-ignore-db = sys # 跳过特定错误(谨慎使用) # slave-skip-errors = 1062,1053 # 中继日志自动清理 relay-log-purge = 1 # 半同步复制插件(可选) # plugin-load = "rpl_semi_sync_slave=semisync_slave.so" # rpl-semi-sync-slave-enabled = 1 # 并行复制(MySQL 5.7+) slave-parallel-type = LOGICAL_CLOCK slave-parallel-workers = 4
-- 2. 重启从服务器 MySQL 服务 -- sudo systemctl restart mysql -- 3. 恢复主服务器数据到从服务器 -- mysql -u root -p < master_backup.sql -- 4. 配置主从复制 CHANGE MASTER TO MASTER_HOST = '192.168.1.100', -- 主服务器IP MASTER_PORT = 3306, MASTER_USER = 'replication_user', MASTER_PASSWORD = 'strong_password', MASTER_LOG_FILE = 'mysql-bin.000001', -- 从主服务器状态获取 MASTER_LOG_POS = 154; -- 从主服务器状态获取 -- 5. 启动从服务器复制 START SLAVE; -- 6. 检查从服务器状态 SHOW SLAVE STATUS\G -- 重要字段说明: -- Slave_IO_Running: Yes -- IO线程运行状态 -- Slave_SQL_Running: Yes -- SQL线程运行状态 -- Seconds_Behind_Master: 0 -- 复制延迟(秒) -- Last_IO_Error: -- IO错误信息 -- Last_SQL_Error: -- SQL错误信息 -- 7. 测试复制 -- 在主服务器上执行: -- INSERT INTO replication_demo.users (username, email) VALUES ('test_user', 'test@example.com'); -- 在从服务器上检查: -- SELECT * FROM replication_demo.users WHERE username = 'test_user';

复制监控和管理

复制状态监控

-- 主服务器监控 -- 查看主服务器状态 SHOW MASTER STATUS; -- 查看连接的从服务器 SHOW SLAVE HOSTS; -- 查看二进制日志状态 SHOW BINARY LOGS; -- 查看主服务器变量 SHOW VARIABLES LIKE 'log_bin%'; SHOW VARIABLES LIKE 'binlog%'; SHOW VARIABLES LIKE 'server_id'; -- 从服务器监控 -- 查看从服务器详细状态 SHOW SLAVE STATUS\G -- 关键监控指标 SELECT 'Replication Status' as metric_type, 'IO Thread' as component, IF(Slave_IO_Running = 'Yes', 'Running', 'Stopped') as status FROM ( SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(@@global.slave_status, 'Slave_IO_Running: ', -1), '\n', 1) as Slave_IO_Running ) t UNION ALL SELECT 'Replication Status', 'SQL Thread', 'Check SHOW SLAVE STATUS'; -- 创建复制监控视图 CREATE VIEW replication_monitor AS SELECT 'Replication Health Check' as report_type, NOW() as check_time, @@server_id as server_id, @@read_only as read_only_status, @@log_bin as binary_log_enabled; SELECT * FROM replication_monitor; -- 复制延迟监控 DELIMITER // CREATE PROCEDURE CheckReplicationLag() BEGIN DECLARE lag_seconds INT; DECLARE io_running VARCHAR(10); DECLARE sql_running VARCHAR(10); -- 注意:这个存储过程需要在从服务器上执行 -- 实际环境中需要通过 SHOW SLAVE STATUS 获取这些值 SELECT 'Replication lag monitoring' as info; SELECT 'Use SHOW SLAVE STATUS to check:' as instruction; SELECT 'Seconds_Behind_Master, Slave_IO_Running, Slave_SQL_Running' as key_fields; -- 示例告警逻辑 SET lag_seconds = 0; -- 从 SHOW SLAVE STATUS 获取 IF lag_seconds > 60 THEN SELECT 'WARNING: Replication lag > 60 seconds' as alert; ELSEIF lag_seconds > 10 THEN SELECT 'CAUTION: Replication lag > 10 seconds' as alert; ELSE SELECT 'OK: Replication lag is acceptable' as alert; END IF; END // DELIMITER ; CALL CheckReplicationLag();

复制故障排除

-- 常见复制问题诊断 -- 1. 检查复制线程状态 SHOW SLAVE STATUS\G -- 2. 查看错误日志 -- tail -f /var/log/mysql/error.log -- 3. 重启复制(当出现错误时) STOP SLAVE; START SLAVE; -- 4. 跳过错误事务(谨慎使用) -- 当遇到特定错误需要跳过时 STOP SLAVE; SET GLOBAL sql_slave_skip_counter = 1; START SLAVE; -- 5. 重新同步从服务器 -- 当数据不一致时,重新从主服务器同步 STOP SLAVE; RESET SLAVE; -- 重新获取主服务器状态 -- 在主服务器上执行:SHOW MASTER STATUS; -- 重新配置复制 CHANGE MASTER TO MASTER_HOST = '192.168.1.100', MASTER_USER = 'replication_user', MASTER_PASSWORD = 'strong_password', MASTER_LOG_FILE = 'mysql-bin.000002', -- 新的日志文件 MASTER_LOG_POS = 1024; -- 新的位置 START SLAVE; -- 6. 检查网络连接 -- 在从服务器上测试到主服务器的连接 -- mysql -h 192.168.1.100 -u replication_user -p -- 7. 检查磁盘空间 SHOW VARIABLES LIKE 'datadir'; -- df -h /var/lib/mysql -- 8. 检查二进制日志 SHOW BINARY LOGS; SHOW BINLOG EVENTS IN 'mysql-bin.000001' LIMIT 5; -- 9. 复制一致性检查 -- 使用 pt-table-checksum 工具(Percona Toolkit) -- pt-table-checksum --host=master_host --databases=replication_demo -- 10. 创建复制健康检查脚本 DELIMITER // CREATE PROCEDURE ReplicationHealthCheck() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE check_result TEXT DEFAULT ''; -- 检查服务器角色 IF @@read_only = 1 THEN SET check_result = CONCAT(check_result, 'Server Role: Slave\n'); -- 这里应该检查 SHOW SLAVE STATUS 的结果 SET check_result = CONCAT(check_result, 'Slave Status: Check SHOW SLAVE STATUS\n'); ELSE SET check_result = CONCAT(check_result, 'Server Role: Master\n'); -- 检查二进制日志 IF @@log_bin = 1 THEN SET check_result = CONCAT(check_result, 'Binary Log: Enabled\n'); ELSE SET check_result = CONCAT(check_result, 'Binary Log: Disabled\n'); END IF; END IF; -- 输出检查结果 SELECT check_result as health_check_result; -- 显示当前配置 SELECT @@server_id as server_id, @@read_only as read_only, @@log_bin as log_bin_enabled, @@binlog_format as binlog_format; END // DELIMITER ; CALL ReplicationHealthCheck();

复制性能优化

-- 复制性能优化配置 -- 1. 并行复制配置(MySQL 5.7+) -- 在从服务器上配置 STOP SLAVE; -- 设置并行复制 SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK'; SET GLOBAL slave_parallel_workers = 4; -- 根据CPU核心数调整 SET GLOBAL slave_preserve_commit_order = 1; START SLAVE; -- 2. 二进制日志优化 -- 在主服务器上配置 SET GLOBAL sync_binlog = 1; -- 安全性优先 -- SET GLOBAL sync_binlog = 0; -- 性能优先(有风险) SET GLOBAL binlog_cache_size = 1048576; -- 1MB SET GLOBAL max_binlog_cache_size = 4294967296; -- 4GB -- 3. 中继日志优化 -- 在从服务器上配置 SET GLOBAL relay_log_purge = 1; -- 自动清理中继日志 SET GLOBAL relay_log_space_limit = 1073741824; -- 1GB -- 4. 网络优化 SET GLOBAL slave_net_timeout = 60; -- 网络超时时间 SET GLOBAL slave_compressed_protocol = 1; -- 启用压缩(高延迟网络) -- 5. 监控复制性能 SHOW STATUS LIKE 'Slave_running'; SHOW STATUS LIKE 'Slave_retried_transactions'; SHOW STATUS LIKE 'Slave_heartbeat_period'; -- 查看复制相关的状态变量 SHOW STATUS LIKE '%slave%'; SHOW STATUS LIKE '%master%'; -- 6. 创建性能监控表 CREATE TABLE replication_performance_log ( id INT AUTO_INCREMENT PRIMARY KEY, server_id INT, lag_seconds INT, io_thread_status VARCHAR(20), sql_thread_status VARCHAR(20), last_error TEXT, check_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 性能监控存储过程 DELIMITER // CREATE PROCEDURE LogReplicationPerformance() BEGIN -- 这个存储过程应该在从服务器上运行 -- 实际实现需要解析 SHOW SLAVE STATUS 的结果 INSERT INTO replication_performance_log (server_id, lag_seconds, io_thread_status, sql_thread_status, last_error) VALUES (@@server_id, 0, 'Running', 'Running', 'No errors'); SELECT 'Performance data logged' as result; END // DELIMITER ; -- 定期执行性能监控 -- 可以通过 cron 或 MySQL Event Scheduler 定期调用 -- CREATE EVENT replication_monitor_event -- ON SCHEDULE EVERY 1 MINUTE -- DO CALL LogReplicationPerformance();

高级复制拓扑

🔗 链式复制

Master → Slave1 → Slave2,适合地理分布式部署

⭐ 星型复制

一个主服务器对应多个从服务器,最常见的拓扑

🔄 双主复制

两个服务器互为主从,实现双向同步

🌐 多源复制

一个从服务器从多个主服务器复制数据

双主复制配置

-- 双主复制配置(Master-Master Replication) -- 服务器A配置 (my.cnf) -- [mysqld] -- server-id = 1 -- log-bin = mysql-bin -- auto-increment-increment = 2 -- auto-increment-offset = 1 -- binlog-do-db = replication_demo -- 服务器B配置 (my.cnf) -- [mysqld] -- server-id = 2 -- log-bin = mysql-bin -- auto-increment-increment = 2 -- auto-increment-offset = 2 -- binlog-do-db = replication_demo -- 在服务器A上创建复制用户 CREATE USER 'repl_user_a'@'%' IDENTIFIED BY 'password_a'; GRANT REPLICATION SLAVE ON *.* TO 'repl_user_a'@'%'; FLUSH PRIVILEGES; -- 在服务器B上创建复制用户 CREATE USER 'repl_user_b'@'%' IDENTIFIED BY 'password_b'; GRANT REPLICATION SLAVE ON *.* TO 'repl_user_b'@'%'; FLUSH PRIVILEGES; -- 在服务器A上配置到服务器B的复制 CHANGE MASTER TO MASTER_HOST = 'server_b_ip', MASTER_USER = 'repl_user_b', MASTER_PASSWORD = 'password_b', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 154; START SLAVE; -- 在服务器B上配置到服务器A的复制 CHANGE MASTER TO MASTER_HOST = 'server_a_ip', MASTER_USER = 'repl_user_a', MASTER_PASSWORD = 'password_a', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 154; START SLAVE; -- 测试双主复制 -- 在服务器A上插入数据 INSERT INTO replication_demo.users (username, email) VALUES ('user_from_a', 'a@example.com'); -- 在服务器B上插入数据 INSERT INTO replication_demo.users (username, email) VALUES ('user_from_b', 'b@example.com'); -- 检查两个服务器上的数据是否一致 SELECT * FROM replication_demo.users ORDER BY id;

多源复制配置 (MySQL 5.7+)

-- 多源复制配置 -- 一个从服务器从多个主服务器复制数据 -- 从服务器配置 (my.cnf) -- [mysqld] -- server-id = 100 -- master-info-repository = TABLE -- relay-log-info-repository = TABLE -- relay-log-recovery = ON -- 配置第一个主服务器的复制通道 CHANGE MASTER TO MASTER_HOST = 'master1_ip', MASTER_USER = 'repl_user1', MASTER_PASSWORD = 'password1', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 154 FOR CHANNEL 'master1'; -- 配置第二个主服务器的复制通道 CHANGE MASTER TO MASTER_HOST = 'master2_ip', MASTER_USER = 'repl_user2', MASTER_PASSWORD = 'password2', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 154 FOR CHANNEL 'master2'; -- 启动所有复制通道 START SLAVE FOR CHANNEL 'master1'; START SLAVE FOR CHANNEL 'master2'; -- 查看多源复制状态 SHOW SLAVE STATUS FOR CHANNEL 'master1'\G SHOW SLAVE STATUS FOR CHANNEL 'master2'\G -- 停止特定通道 STOP SLAVE FOR CHANNEL 'master1'; -- 重置特定通道 RESET SLAVE FOR CHANNEL 'master1'; -- 查看所有复制通道 SELECT CHANNEL_NAME, HOST, PORT, USER, SOURCE_LOG_FILE, SOURCE_LOG_POS FROM performance_schema.replication_connection_configuration; -- 查看复制应用状态 SELECT CHANNEL_NAME, SERVICE_STATE, LAST_ERROR_MESSAGE, LAST_ERROR_TIMESTAMP FROM performance_schema.replication_applier_status;

故障转移和高可用

手动故障转移

-- 手动故障转移步骤 -- 1. 检测主服务器故障 -- 在监控系统中检测主服务器是否响应 -- mysql -h master_ip -u monitor_user -p -e "SELECT 1;" -- 2. 选择新的主服务器 -- 选择数据最新、延迟最小的从服务器 -- 在候选从服务器上检查复制状态 SHOW SLAVE STATUS\G -- 3. 停止所有从服务器的复制 STOP SLAVE; -- 4. 在新主服务器上启用写入 SET GLOBAL read_only = 0; SET GLOBAL super_read_only = 0; -- 5. 重新配置其他从服务器 -- 获取新主服务器的状态 SHOW MASTER STATUS; -- 在其他从服务器上重新配置复制 CHANGE MASTER TO MASTER_HOST = 'new_master_ip', MASTER_USER = 'replication_user', MASTER_PASSWORD = 'password', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 154; START SLAVE; -- 6. 更新应用程序配置 -- 修改应用程序的数据库连接配置,指向新的主服务器 -- 7. 验证故障转移 -- 测试写入操作 INSERT INTO replication_demo.users (username, email) VALUES ('failover_test', 'test@example.com'); -- 检查从服务器是否正常复制 SELECT * FROM replication_demo.users WHERE username = 'failover_test';

自动故障转移脚本

#!/bin/bash # mysql_failover.sh - MySQL 自动故障转移脚本 # 配置参数 MASTER_HOST="192.168.1.100" SLAVE_HOSTS=("192.168.1.101" "192.168.1.102" "192.168.1.103") MYSQL_USER="admin" MYSQL_PASS="password" REPL_USER="replication_user" REPL_PASS="repl_password" LOG_FILE="/var/log/mysql_failover.log" # 日志函数 log_message() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE } # 检查服务器连接 check_server() { local host=$1 mysql -h $host -u $MYSQL_USER -p$MYSQL_PASS -e "SELECT 1;" > /dev/null 2>&1 return $? } # 获取从服务器延迟 get_slave_lag() { local host=$1 local lag=$(mysql -h $host -u $MYSQL_USER -p$MYSQL_PASS -e \ "SHOW SLAVE STATUS\G" | grep "Seconds_Behind_Master" | awk '{print $2}') echo ${lag:-999999} } # 选择最佳从服务器作为新主服务器 select_new_master() { local best_slave="" local min_lag=999999 for slave in "${SLAVE_HOSTS[@]}"; do if check_server $slave; then local lag=$(get_slave_lag $slave) log_message "Slave $slave lag: $lag seconds" if [ $lag -lt $min_lag ]; then min_lag=$lag best_slave=$slave fi else log_message "Slave $slave is not accessible" fi done echo $best_slave } # 提升从服务器为主服务器 promote_slave_to_master() { local new_master=$1 log_message "Promoting $new_master to master" # 停止复制 mysql -h $new_master -u $MYSQL_USER -p$MYSQL_PASS -e "STOP SLAVE;" # 启用写入 mysql -h $new_master -u $MYSQL_USER -p$MYSQL_PASS -e \ "SET GLOBAL read_only = 0; SET GLOBAL super_read_only = 0;" # 重置从服务器状态 mysql -h $new_master -u $MYSQL_USER -p$MYSQL_PASS -e "RESET SLAVE ALL;" log_message "$new_master promoted to master successfully" } # 重新配置其他从服务器 reconfigure_slaves() { local new_master=$1 # 获取新主服务器状态 local master_status=$(mysql -h $new_master -u $MYSQL_USER -p$MYSQL_PASS -e \ "SHOW MASTER STATUS\G") local log_file=$(echo "$master_status" | grep "File:" | awk '{print $2}') local log_pos=$(echo "$master_status" | grep "Position:" | awk '{print $2}') log_message "New master status: $log_file, $log_pos" for slave in "${SLAVE_HOSTS[@]}"; do if [ "$slave" != "$new_master" ] && check_server $slave; then log_message "Reconfiguring slave $slave" # 停止复制 mysql -h $slave -u $MYSQL_USER -p$MYSQL_PASS -e "STOP SLAVE;" # 重新配置主服务器 mysql -h $slave -u $MYSQL_USER -p$MYSQL_PASS -e " CHANGE MASTER TO MASTER_HOST = '$new_master', MASTER_USER = '$REPL_USER', MASTER_PASSWORD = '$REPL_PASS', MASTER_LOG_FILE = '$log_file', MASTER_LOG_POS = $log_pos; " # 启动复制 mysql -h $slave -u $MYSQL_USER -p$MYSQL_PASS -e "START SLAVE;" log_message "Slave $slave reconfigured successfully" fi done } # 发送告警通知 send_alert() { local message=$1 log_message "ALERT: $message" # 发送邮件告警 echo "$message" | mail -s "MySQL Failover Alert" admin@example.com # 发送到监控系统 # curl -X POST "http://monitoring-system/alert" -d "message=$message" } # 主故障转移流程 main_failover() { log_message "Starting MySQL failover process" # 检查主服务器状态 if check_server $MASTER_HOST; then log_message "Master server $MASTER_HOST is accessible, no failover needed" return 0 fi log_message "Master server $MASTER_HOST is not accessible, starting failover" send_alert "Master server $MASTER_HOST failed, starting automatic failover" # 选择新的主服务器 local new_master=$(select_new_master) if [ -z "$new_master" ]; then log_message "No suitable slave found for promotion" send_alert "Failover failed: No suitable slave server available" return 1 fi log_message "Selected $new_master as new master" # 执行故障转移 promote_slave_to_master $new_master reconfigure_slaves $new_master log_message "Failover completed successfully" send_alert "Failover completed: $new_master is now the master server" # 更新配置文件或DNS记录 # update_application_config $new_master return 0 } # 执行故障转移 main_failover

使用 MHA 进行自动故障转移

# MHA (Master High Availability) 是专业的 MySQL 高可用解决方案 # 1. 安装 MHA # 在管理节点安装 MHA Manager # yum install mha4mysql-manager # 在所有 MySQL 节点安装 MHA Node # yum install mha4mysql-node # 2. 配置 MHA # 创建 MHA 配置文件 /etc/mha/app1.cnf [server default] manager_log=/var/log/mha/app1/manager.log manager_workdir=/var/log/mha/app1 master_binlog_dir=/var/lib/mysql user=mha password=mha_password ping_interval=3 repl_user=replication_user repl_password=repl_password ssh_user=root [server1] hostname=192.168.1.100 port=3306 candidate_master=1 [server2] hostname=192.168.1.101 port=3306 candidate_master=1 [server3] hostname=192.168.1.102 port=3306 no_master=1 # 3. 检查 MHA 配置 masterha_check_ssh --conf=/etc/mha/app1.cnf masterha_check_repl --conf=/etc/mha/app1.cnf # 4. 启动 MHA Manager masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover # 5. 监控 MHA 状态 masterha_check_status --conf=/etc/mha/app1.cnf # 6. 手动故障转移 masterha_master_switch --conf=/etc/mha/app1.cnf --master_state=dead --dead_master_host=192.168.1.100 --new_master_host=192.168.1.101 # 7. 在线主服务器切换 masterha_master_switch --conf=/etc/mha/app1.cnf --master_state=alive --new_master_host=192.168.1.101 --orig_master_is_new_slave

最佳实践和注意事项

🎯 主从复制最佳实践:
  1. 监控复制延迟:建立实时监控,及时发现复制问题
  2. 定期检查一致性:使用工具验证主从数据一致性
  3. 合理配置参数:根据业务需求调整复制相关参数
  4. 网络优化:确保主从服务器间网络稳定可靠
  5. 故障转移演练:定期进行故障转移测试
  6. 备份策略:主从复制不能替代备份
  7. 权限管理:严格控制复制用户权限
⚠️ 常见问题和注意事项:
  • 数据不一致:避免在从服务器上进行写操作
  • 复制延迟:监控并优化网络和配置参数
  • 二进制日志清理:合理设置日志保留期限
  • 磁盘空间:监控中继日志和二进制日志占用空间
  • 字符集问题:确保主从服务器字符集一致
  • 时区设置:保持主从服务器时区同步
  • 版本兼容性:注意 MySQL 版本间的兼容性
< 1s
理想复制延迟
99.9%
目标可用性
< 30s
故障转移时间
0
数据丢失容忍度
-- 清理示例对象 DROP VIEW IF EXISTS replication_monitor; DROP TABLE IF EXISTS replication_performance_log; DROP PROCEDURE IF EXISTS CheckReplicationLag; DROP PROCEDURE IF EXISTS LogReplicationPerformance; DROP PROCEDURE IF EXISTS ReplicationHealthCheck; DROP DATABASE IF EXISTS replication_demo; SELECT 'MySQL replication tutorial completed. All example objects cleaned up.' AS message;