社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

MySQL主从复制延迟诊断与GTID故障切换:零数据丢失完整方案

马哥Linux运维 • 8 月前 • 279 次点击  

MySQL主从复制延迟诊断与GTID故障切换:零数据丢失完整方案

适用场景 & 前置条件

适用业务:读写分离架构、高可用数据库集群、跨地域容灾、数据仓库 ETL 同步前置条件

  • • MySQL ≥ 5.7(推荐 8.0+,GTID 增强特性)
  • • 主从网络延迟 < 10ms(同机房)/ < 50ms(跨地域)
  • • 主库已启用二进制日志(log_bin=ON
  • • 从库磁盘 I/O 性能 ≥ 主库(SSD 推荐)
  • • Root 或 SUPER 权限账号

环境与版本矩阵

组件
版本要求
关键特性
复制延迟(典型值)
MySQL 5.7
5.7.17+
GTID, 多线程复制, 半同步
< 1s(局域网)
MySQL 8.0
8.0.23+
GTID 自动定位, Writeset 并行复制
< 500ms
MariaDB 10.5+
10.5+
GTID 兼容, 多源复制
< 1s
MHA
0.58
自动故障切换(传统复制)
-
Orchestrator
3.2+
GTID 故障切换与拓扑管理
-

快速清单(Checklist)

  1. 1. 验证主从复制状态SHOW SLAVE STATUS
  2. 2. 诊断复制延迟根因(网络/SQL 线程/大事务)
  3. 3. 启用 GTID 模式(在线迁移或新建)
  4. 4. 配置半同步复制(防数据丢失)
  5. 5. 优化多线程复制(并行回放)
  6. 6. 监控复制延迟与告警Seconds_Behind_Master
  7. 7. 测试故障切换(主库宕机场景)
  8. 8. 执行 GTID 故障切换CHANGE MASTER TO 自动定位)
  9. 9. 验证数据一致性pt-table-checksum
  10. 10. 配置自动故障切换工具(Orchestrator/MHA)

实施步骤

Step 1:验证主从复制状态

在从库执行

SHOW SLAVE STATUS\G

关键字段解读

***************************1.row***************************
               Slave_IO_State: Waiting for master to send event  -- IO 线程状态
                  Master_Host: 192.168.1.10
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000023-- 主库当前 binlog
          Read_Master_Log_Pos: 45678901-- 已读取位置
               Relay_Log_File: relay-bin.000012
                Relay_Log_Pos: 45678654
        Relay_Master_Log_File: mysql-bin.000023
             Slave_IO_Running: Yes                               -- IO 线程正常
            Slave_SQL_Running: Yes                               -- SQL 线程正常
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0-- 无错误
                   Last_Error:                                   -- 错误信息(空=正常)
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 45678654-- 已执行位置
              Relay_Log_Space: 23456789
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 2-- 复制延迟(秒)
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
                  Master_UUID: a1b2c3d4-e5f6-11ed-9876-000c29123456
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: a1b2c3d4-e5f6-11ed-9876-000c29123456:1-12345-- 已接收的 GTID
            Executed_Gtid_Set: a1b2c3d4-e5f6-11ed-9876-000c29123456:1-12340-- 已执行的 GTID
                Auto_Position: 1-- GTID 自动定位已启用
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 0

健康检查要点

  • • Slave_IO_Running 与 Slave_SQL_Running 必须为 Yes
  • • Seconds_Behind_Master 应 < 5 秒(理想值 < 1 秒)
  • • Last_Errno / Last_SQL_Errno 应为 0
  • • Retrieved_Gtid_Set 与 Executed_Gtid_Set 差距 < 10 个事务

快速诊断命令

# 检查主从状态(简化版)
mysql -e "SHOW SLAVE STATUS\G" | grep -E "Running|Behind|Error"

# 查看 GTID 差异
mysql -e "SHOW SLAVE STATUS\G" | grep -E "Retrieved_Gtid_Set|Executed_Gtid_Set"

Step 2:诊断复制延迟根因

场景 1:网络延迟

# 测试主从网络延迟
ping -c 10 192.168.1.10

# 测试 MySQL 端口连通性与延迟
time mysql -h 192.168.1.10 -u repl -p -e "SELECT 1"

场景 2:大事务阻塞

-- 在主库查看当前运行的大事务
SELECT*FROM information_schema.INNODB_TRX
WHERE trx_started < NOW() -INTERVAL30SECOND
ORDERBY trx_started;

-- 查看二进制日志中的大事务
SHOW BINLOG EVENTS IN'mysql-bin.000023' LIMIT 10;

场景 3:从库 SQL 线程单线程回放

-- 查看从库并行回放配置
SHOW VARIABLES LIKE'slave_parallel%';

-- 查看当前并行回放线程数
SELECTCOUNT(*FROM performance_schema.replication_applier_status_by_worker;

场景 4:从库磁盘 I/O 瓶颈

# 监控从库磁盘 I/O
iostat -x 1 10 | grep -E "Device|sd"

# 查看 MySQL I/O 等待
mysql -e "SHOW PROCESSLIST" | grep "Waiting for"

诊断脚本(综合检查):

#!/bin/bash
# /usr/local/bin/diagnose_replication_lag.sh

echo"=== 主从复制延迟诊断 ==="

# 1. 复制延迟值
DELAY=$(mysql -ss -e "SHOW SLAVE STATUS\G" | grep "Seconds_Behind_Master:" | awk '{print $2}')
echo"当前延迟:$DELAY 秒"

# 2. IO 线程状态
IO_STATE=$(mysql -ss -e "SHOW SLAVE STATUS\G" | grep "Slave_IO_Running:" | awk '{print $2}')
echo"IO 线程:$IO_STATE"

# 3. SQL 线程状态
SQL_STATE=$(mysql -ss -e "SHOW SLAVE STATUS\G" | grep "Slave_SQL_Running:" | awk '{print $2}')
echo"SQL 线程:$SQL_STATE"

# 4. GTID 差异
RETRIEVED=$(mysql -ss -e "SHOW SLAVE STATUS\G" | grep "Retrieved_Gtid_Set:" | awk -F: '{print $NF}' | awk -F- '{print $NF}')
EXECUTED=$(mysql -ss -e "SHOW SLAVE STATUS\G" | grep "Executed_Gtid_Set:" | awk -F: '{print $NF}' | awk -F- '{print $NF}')
GTID_GAP=$((RETRIEVED - EXECUTED))
echo"GTID 待执行:$GTID_GAP 个事务"

# 5. 网络延迟
MASTER_HOST=$(mysql -ss -e "SHOW SLAVE STATUS\G" | grep "Master_Host:" | awk '{print $2}')
PING_LATENCY=$(ping -c 5 $MASTER_HOST | tail -1 | awk -F'/''{print $5}')
echo"网络延迟:$PING_LATENCY ms"

# 6. 从库并行回放
PARALLEL_WORKERS=$(mysql -ss -e "SHOW VARIABLES LIKE 'slave_parallel_workers'" | awk '{print $2}')
echo"并行回放线程数:$PARALLEL_WORKERS"

Step 3:启用 GTID 模式(在线迁移)

前置检查(确保兼容性):

-- 检查是否有非事务引擎表(MyISAM)
SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE
FROM information_schema.TABLES
WHERE ENGINE !='InnoDB'AND TABLE_SCHEMA NOTIN ('mysql','information_schema','performance_schema','sys');

-- 检查是否有存储过程使用非确定性函数
SELECT ROUTINE_SCHEMA, ROUTINE_NAME, SQL_MODE
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA NOTIN ('mysql','sys'AND SQL_MODE NOTLIKE'%STRICT%';

在线启用 GTID(MySQL 5.7.6+):

Step 1:主库配置

# /etc/my.cnf [mysqld] 段添加
gtid_mode=ON_PERMISSIVE               # 允许 GTID 与非 GTID 事务并存
enforce_gtid_consistency= ON# 强制 GTID 一致性检查

重启主库

systemctl restart mysqld

Step 2:从库配置

# /etc/my.cnf
gtid_mode=ON_PERMISSIVE
enforce_gtid_consistency=ON

重启从库

systemctl restart mysqld

Step 3:主库切换到纯 GTID 模式

-- 在主库执行
SETGLOBAL gtid_mode=ON;

Step 4:从库切换到纯 GTID 模式并启用自动定位

-- 在从库执行
STOP SLAVE;
SETGLOBAL gtid_mode=ON;
CHANGE MASTER TO MASTER_AUTO_POSITION=1;
START SLAVE;

验证 GTID 启用

-- 主库
SHOW MASTER STATUS\G

-- 从库
SHOW SLAVE STATUS\G | grep Auto_Position
# 预期输出:Auto_Position: 1

Step 4:配置半同步复制(防数据丢失)

安装半同步插件

主库

INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SETGLOBAL rpl_semi_sync_master_enabled=1;
SETGLOBAL rpl_semi_sync_master_timeout=1000;  -- 超时 1 秒降级为异步

从库

INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SETGLOBAL rpl_semi_sync_slave_enabled=1;
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;

持久化配置/etc/my.cnf

# 主库
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout =1000

# 从库
[mysqld]
rpl_semi_sync_slave_enabled=1

验证半同步状态

-- 主库
SHOW STATUS LIKE'Rpl_semi_sync_master_status';
-- 预期:ON

SHOW STATUS LIKE'Rpl_semi_sync_master_clients';
-- 预期:>= 1(半同步从库数量)

-- 从库
SHOW STATUS LIKE'Rpl_semi_sync_slave_status';
-- 预期:ON

监控半同步性能

-- 主库半同步等待时间(微秒)
SHOW STATUS LIKE'Rpl_semi_sync_master_tx_avg_wait_time';

-- 半同步超时次数(频繁超时需优化网络)
SHOW STATUS LIKE'Rpl_semi_sync_master_no_tx';

Step 5:优化多线程复制(并行回放)

MySQL 5.7 多线程配置

# /etc/my.cnf [mysqld]
slave_parallel_type=LOGICAL_CLOCK          # 基于组提交的并行复制
slave_parallel_workers=4# 并行线程数(建议 = CPU 核心数)
slave_preserve_commit_order=1# 保持事务提交顺序

MySQL 8.0 增强配置

# /etc/my.cnf [mysqld]
slave_parallel_type=LOGICAL_CLOCK
slave_parallel_workers=8
binlog_transaction_dependency_tracking=WRITESET  -- 基于 Writeset 的并行复制
transaction_write_set_extraction=XXHASH64        -- 写集合哈希算法

重启从库应用配置

systemctl restart mysqld

验证并行回放生效

-- 查看并行线程
SELECT*FROM performance_schema.replication_applier_status_by_worker;

-- 查看并行回放统计
SHOW STATUS LIKE'Slave_parallel%';

预期输出

+------------------------------+-------+
| Variable_name                |Value|
+------------------------------+-------+
| Slave_parallel_workers       |4|
| Slave_parallel_running       |4|
+------------------------------+-------+

Step 6:监控复制延迟与告警

通过 MySQL Exporter 暴露指标

# 安装 mysqld_exporter
wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.15.0/mysqld_exporter-0.15.0.linux-amd64.tar.gz
tar xzf mysqld_exporter-0.15.0.linux-amd64.tar.gz
sudocp mysqld_exporter-0.15.0.linux-amd64/mysqld_exporter /usr/local/bin/

# 创建监控账号
mysql -e "CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'password' WITH MAX_USER_CONNECTIONS 3;"
mysql -e "GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';"

# 创建配置文件
cat > /etc/.mysqld_exporter.cnf <<EOF
[client]
user=exporter
password=password
EOF


# 创建 systemd 服务
sudotee /etc/systemd/system/mysqld_exporter.service <<EOF
[Unit]
Description=MySQL Exporter
After=network.target

[Service]
Type=simple
User=mysql
ExecStart=/usr/local/bin/mysqld_exporter --config.my-cnf=/etc/.mysqld_exporter.cnf
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF


# 启动服务
sudo systemctl daemon-reload
sudo systemctl enable mysqld_exporter
sudo systemctl start mysqld_exporter

# 验证指标
curl http://localhost:9104/metrics | grep mysql_slave_status_seconds_behind_master

Prometheus 告警规则

groups:
-name:mysql-replication
rules:
-alert:MySQLReplicationLag
expr:mysql_slave_status_seconds_behind_master>30
for:5m
labels:
severity:warning
annotations:
summary:"MySQL 复制延迟超过 30 秒"

-alert:MySQLReplicationStopped
expr:mysql_slave_status_slave_io_running==0ormysql_slave_status_slave_sql_running==0
for:1m
labels:
severity:critical
annotations:
summary:"MySQL 复制线程停止"

-alert:MySQLReplicationError
expr:mysql_slave_status_last_errno>0
for:1m
labels:
severity:critical
annotations:
summary:"MySQL 复制错误(Errno: {{ $value }})"

-alert:MySQLSemiSyncDisabled
expr:mysql_global_status_rpl_semi_sync_master_status==0
for:5m
labels:
severity:warning
annotations:
summary:"MySQL 半同步复制已降级为异步"

Grafana 面板查询

# 复制延迟(秒)
mysql_slave_status_seconds_behind_master

# IO/SQL 线程状态(1=Running, 0=Stopped)
mysql_slave_status_slave_io_running
mysql_slave_status_slave_sql_running

# GTID 执行进度
mysql_slave_status_executed_gtid_set

Step 7:测试故障切换(模拟主库宕机)

准备工作

-- 在所有从库确认复制延迟 = 0
SHOW SLAVE STATUS\G | grep Seconds_Behind_Master

-- 记录当前主库的 GTID
-- 主库
SHOW MASTER STATUS\G

-- 从库
SHOW SLAVE STATUS\G | grep Executed_Gtid_Set

模拟主库宕机

# 在主库执行
systemctl stop mysqld

选举新主库(选择 GTID 最新的从库):

# 在所有从库执行
mysql -e "SHOW SLAVE STATUS\G" | grep Executed_Gtid_Set

# 比较输出,选择 GTID 序号最大的从库作为新主
# 示例输出:
# 从库 1:a1b2c3d4-e5f6-11ed-9876-000c29123456:1-12345
# 从库 2:a1b2c3d4-e5f6-11ed-9876-000c29123456:1-12340
# 选择从库 1 作为新主(12345 > 12340)

Step 8:执行 GTID 故障切换

Step 1:在新主库停止复制

STOP SLAVE;
RESET SLAVE ALL;  -- 清除复制配置

Step 2:在新主库启用写入

SETGLOBAL read_only=0;
SETGLOBAL super_read_only=0;

Step 3:在其他从库重新指向新主库

-- 在从库 2/3/... 执行
STOP SLAVE;

CHANGE MASTER TO
  MASTER_HOST='new-master-ip',
  MASTER_USER='repl',
  MASTER_PASSWORD='password',
  MASTER_PORT=3306,
  MASTER_AUTO_POSITION=1;  -- GTID 自动定位

START SLAVE;

-- 验证状态
SHOW SLAVE STATUS\G

Step 4:验证数据一致性

# 在新主库执行测试写入
mysql -e "CREATE DATABASE test_failover; USE test_failover; CREATE TABLE t1(id INT); INSERT INTO t1 VALUES(1);"

# 在从库验证
mysql -e "SELECT * FROM test_failover.t1;"
# 预期输出:id = 1

Step 5:更新应用连接配置(指向新主库):

# 更新应用配置文件或通过 VIP 漂移
# 示例:通过 keepalived VIP 自动切换

Step 9:验证数据一致性

安装 Percona Toolkit

# RHEL/CentOS
sudo yum install -y percona-toolkit

# Ubuntu/Debian
sudo apt install -y percona-toolkit

执行一致性校验

# 在主库执行
pt-table-checksum \
  --host=localhost \
  --user=root \
  --password=password \
  --databases=mydb \
  --replicate=percona.checksums \
  --no-check-binlog-format

# 输出示例
TS            ERRORS  DIFFS  ROWS  DIFF_ROWS  CHUNKS SKIPPED    TIME TABLE
10-31T10:30:00     0      0  1000          0       1       0   0.123 mydb.users
10-31T10:30:01     0      0  5000          0       2       0   0.456 mydb.orders

修复不一致数据

# 如发现 DIFFS > 0,使用 pt-table-sync 修复
pt-table-sync \
  --execute \
  --sync-to-master \
  h=slave-host,u=root,p=password \
  --databases=mydb \
  --tables=users

Step 10:配置自动故障切换工具(Orchestrator)

安装 Orchestrator

# 下载
wget https://github.com/openark/orchestrator/releases/download/v3.2.6/orchestrator-3.2.6-1.x86_64.rpm

# 安装
sudo rpm -ivh orchestrator-3.2.6-1.x86_64.rpm

# 或使用 Docker
docker run -d \
  --name orchestrator \
  -p 3000:3000 \
  -e ORC_TOPOLOGY_USER=orc_user \
  -e ORC_TOPOLOGY_PASSWORD=password \
  openark/orchestrator:latest

配置数据库连接/etc/orchestrator.conf.json

{
"MySQLTopologyUser":"orc_user",
"MySQLTopologyPassword":"password",
"MySQLOrchestratorHost":"127.0.0.1",
"MySQLOrchestratorPort":3306,
"MySQLOrchestratorDatabase":"orchestrator",
"MySQLOrchestratorUser":"orc_server",
"MySQLOrchestratorPassword":"orc_password",
"RecoveryPeriodBlockSeconds":300,
"RecoverMasterClusterFilters":["*"],
"RecoverIntermediateMasterClusterFilters":["*"],
"ApplyMySQLPromotionAfterMasterFailover":true
}

创建 Orchestrator 数据库

CREATE DATABASE orchestrator;
CREATEUSER'orc_server'@'%' IDENTIFIED BY'orc_password';
GRANTALLON orchestrator.*TO'orc_server'@'%';

-- 在所有 MySQL 节点创建拓扑用户
CREATEUSER'orc_user'@'%' IDENTIFIED BY'password';
GRANT SUPER, PROCESS, REPLICATION SLAVE, REPLICATION CLIENT, RELOAD ON*.*TO'orc_user'@'%';

启动 Orchestrator

systemctl enable orchestrator
systemctl start orchestrator

# 访问 Web UI
http://your-server:3000

发现拓扑

# 通过 API 发现主库
curl -X POST http://localhost:3000/api/discover/192.168.1.10/3306

# 查看拓扑
curl http://localhost:3000/api/clusters-info | jq

测试自动故障切换

# 模拟主库宕机
ssh 192.168.1.10 "systemctl stop mysqld"

# 观察 Orchestrator 日志
tail -f /var/log/orchestrator/orchestrator.log

# 预期输出:检测到主库宕机 → 选举新主 → 重新配置从库

监控与告警

关键监控指标

-- 复制延迟
SHOW SLAVE STATUS\G | grep Seconds_Behind_Master

-- GTID 执行进度
SELECT @@GLOBAL.gtid_executed;

-- 半同步状态
SHOW STATUS LIKE'Rpl_semi_sync%';

-- 复制错误统计
SHOW SLAVE STATUS\G | grep -E "Last_Errno|Last_Error"

Prometheus 监控指标

# 复制延迟超过 10 秒
mysql_slave_status_seconds_behind_master > 10

# IO/SQL 线程停止
mysql_slave_status_slave_io_running == 0
mysql_slave_status_slave_sql_running == 0

# 半同步降级
mysql_global_status_rpl_semi_sync_master_status == 0

# GTID 待执行事务数
mysql_slave_status_retrieved_gtid_set - mysql_slave_status_executed_gtid_set > 100

性能与容量

复制延迟优化

瓶颈
诊断方法
优化方案
网络延迟
ping
 / mtr
专线/内网直连/半同步超时调优
单线程回放
SHOW PROCESSLIST
启用多线程复制(slave_parallel_workers
大事务阻塞
SHOW INNODB STATUS
拆分大事务/增加 binlog_row_image=MINIMAL
磁盘 I/O 慢
iostat -x
升级 SSD/调整 innodb_flush_log_at_trx_commit

容量规划

从库规格建议

  • • CPU:≥ 主库 × 0.8(多线程回放需要更多核心)
  • • 内存:= 主库(innodb_buffer_pool_size 相同)
  • • 磁盘:≥ 主库(SSD 推荐,IOPS ≥ 主库)
  • • 网络:≥ 10Gbps(高并发写入场景)

安全与合规

复制账号权限最小化

-- 创建复制专用账号
CREATEUSER'repl'@'%' IDENTIFIED BY'StrongPassword123!';
GRANT REPLICATION SLAVE ON*.*TO'repl'@'%';

-- 禁止使用 root 账号复制

SSL 加密复制

-- 主库生成 SSL 证书(使用 mysql_ssl_rsa_setup)
mysql_ssl_rsa_setup --datadir=/var/lib/mysql

-- 从库配置 SSL 复制
STOP SLAVE;
CHANGE MASTER TO
  MASTER_SSL=1,
  MASTER_SSL_CA='/var/lib/mysql/ca.pem',
  MASTER_SSL_CERT='/var/lib/mysql/client-cert.pem',
  MASTER_SSL_KEY='/var/lib/mysql/client-key.pem';
START SLAVE;

-- 验证 SSL 启用
SHOW SLAVE STATUS\G | grep Master_SSL_Allowed
# 预期:Master_SSL_Allowed: Yes

合规核对点

  • • [ ] 复制账号使用强密码(≥ 16 字符)
  • • [ ] 跨公网复制启用 SSL 加密
  • • [ ] 从库设置为只读(read_only=1
  • • [ ] 半同步复制已启用(防数据丢失)
  • • [ ] 复制延迟告警已配置(< 30 秒)
  • • [ ] 定期执行数据一致性校验(pt-table-checksum
  • • [ ] 故障切换剧本已演练并文档化

常见故障与排错

症状
诊断命令
可能根因
快速修复
永久修复
IO 线程停止
SHOW SLAVE STATUS\G
网络中断/主库宕机
START SLAVE IO_THREAD
检查网络/切换主库
SQL 线程停止
SHOW SLAVE STATUS\G
复制错误(如主键冲突)
跳过错误事务(SET GLOBAL sql_slave_skip_counter=1
修复数据冲突
复制延迟持续增大
iostat
 / SHOW PROCESSLIST
磁盘 I/O 瓶颈/大事务
临时停止写入/扩容
优化 SQL/增加并行线程
GTID 不一致
SELECT @@gtid_executed
从库手动写入
使用 RESET MASTER 重建
确保从库 read_only=1
半同步降级
SHOW STATUS LIKE 'Rpl_semi_sync%'
从库延迟/网络抖动
增大 rpl_semi_sync_master_timeout
优化网络/增加半同步从库

变更与回滚剧本

维护窗口

推荐时间:凌晨 2:00 - 4:00(业务低峰期)变更前置条件

  • • [ ] 备份主库数据(mysqldump 或物理备份)
  • • [ ] 确认复制延迟 < 1 秒
  • • [ ] 准备回滚 SQL 脚本
  • • [ ] 通知业务方(只读维护时间)

灰度策略

阶段 1:单从库验证

# 在单个从库测试配置变更
mysql -h slave-01 -e "STOP SLAVE; SET GLOBAL slave_parallel_workers=8; START SLAVE;"

# 观察 10 分钟
watch -n 10 'mysql -h slave-01 -e "SHOW SLAVE STATUS\G" | grep Seconds_Behind_Master'

阶段 2:批量应用

# Ansible 批量配置
ansible mysql-slaves -m shell -a "mysql -e 'STOP SLAVE; SET GLOBAL slave_parallel_workers=8; START SLAVE;'"

回退条件与命令

触发条件

  • • 复制延迟 > 60 秒持续 10 分钟
  • • SQL 线程频繁停止
  • • 数据一致性校验失败

回退操作

-- 恢复原配置
STOP SLAVE;
SETGLOBAL slave_parallel_workers=0;  -- 改回单线程
START SLAVE;

最佳实践

  1. 1. 始终启用 GTID:简化故障切换与拓扑变更
  2. 2. 启用半同步复制:关键业务场景防数据丢失(至少 1 个半同步从库)
  3. 3. 多线程复制必选slave_parallel_workers ≥ 4(MySQL 8.0 用 WRITESET)
  4. 4. 从库只读保护read_only=1 + super_read_only=1
  5. 5. 监控复制延迟:告警阈值 < 30 秒
  6. 6. 定期一致性校验:每周执行 pt-table-checksum
  7. 7. 自动化故障切换:生产环境部署 Orchestrator/MHA
  8. 8. 避免从库手动写入:破坏 GTID 一致性
  9. 9. 大事务拆分:单个事务不超过 1GB(避免复制阻塞)
  10. 10. 故障切换演练:每季度演练一次(包含数据验证)

附录

完整主从配置模板

主库/etc/my.cnf

[mysqld]
server_id=1
log_bin=mysql-bin
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=ON
log_slave_updates=ON

# 半同步复制
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000

# 二进制日志保留
expire_logs_days=7
max_binlog_size=1G

# 性能优化
sync_binlog=1
innodb_flush_log_at_trx_commit=1

从库/etc/my.cnf

[mysqld]
server_id=2
log_bin=mysql-bin
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=ON
log_slave_updates=ON
read_only=1
super_read_only=1

# 半同步复制
rpl_semi_sync_slave_enabled=1

# 多线程复制
slave_parallel_type=LOGICAL_CLOCK
slave_parallel_workers=8
slave_preserve_commit_order=1

# MySQL 8.0 增强
binlog_transaction_dependency_tracking=WRITESET
transaction_write_set_extraction=XXHASH64

# Relay log
relay_log=relay-bin
relay_log_recovery=ON

Ansible 自动化部署 Playbook

---
-name:配置MySQL主从复制
hosts:mysql_slaves
become:yes
vars:
master_host:"192.168.1.10"
repl_user:"repl"
repl_password:"StrongPassword123!"

tasks:
-name:停止从库复制
mysql_replication:
mode:stopslave

-name:配置主库连接
mysql_replication:
mode:changemaster
master_host:"{{ master_host }}"
master_user:"{{ repl_user }}"
master_password:"{{ repl_password }}"
master_auto_position:yes

-name:启动从库复制
mysql_replication:
mode:startslave

-name:验证复制状态
mysql_replication:
mode:getslave
register:slave_status
failed_when:slave_status.Slave_IO_Running!='Yes'orslave_status.Slave_SQL_Running!='Yes'

-name:显示复制延迟
debug:
msg:"复制延迟:{{ slave_status.Seconds_Behind_Master }} 秒"

测试环境:MySQL 8.0.35, RHEL 8.8 / Ubuntu 22.04 LTS测试日期:2025-10-31维护周期:配置每季度审查,一致性校验每周执行,故障切换每季度演练

文末福利


网络监控是保障网络系统和数据安全的重要手段,能够帮助运维人员及时发现并应对各种问题,及时发现并解决,从而确保网络的顺畅运行。

谢谢一路支持,给大家分享6款开源免费的网络监控工具,并准备了对应的资料文档,建议运维工程师收藏(文末一键领取)。

图片
备注:【监控合集】

图片

100%免费领取


一、zabbix

图片
图片

二、Prometheus


图片

内容较多,6款常用网络监控工具(zabbix、Prometheus、Cacti、Grafana、OpenNMS、Nagios不再一一介绍, 需要的朋友扫码备注【监控合集】,即可100%免费领取。

图片

 以上所有资料获取请扫码

备注:【监控合集】

图片

100%免费领取

(后台不再回复,扫码一键领取)


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/188641