14.8.7 灾备与数据一致性保障

本节围绕ProxySQL在高可用场景下的灾备与数据一致性保障展开,目标是“可用性优先、数据一致性可控、恢复路径清晰”。灾备体系需从架构、数据复制、应用接入三层协同设计,覆盖同城双活、异地多活与冷/热备模式,并明确RPO/RTO。

原理草图(同城双活 + 异地灾备):

文章图片

关键策略要点:
- 写流量只进入主库主机组;读流量按延迟阈值、只读标记与健康检查动态选从库。
- 主库故障切换后强制刷新ProxySQL后端状态,避免“脑裂写入”。
- 异地灾备采用异步复制并控制读延迟剔除,保障最终一致性窗口。

安装与基础准备(示例)#

以两台ProxySQL为例(proxysql01/02),基于官方仓库安装:

# 1) 安装ProxySQL
sudo yum install -y https://repo.proxysql.com/ProxySQL/proxysql-2.5.x-el7.x86_64.rpm
sudo systemctl enable --now proxysql

# 2) 登录管理端
mysql -uadmin -padmin -h127.0.0.1 -P6032

# 3) 查看版本
SELECT @@version;

复制监控与一致性控制(示例)#

配置mysql-monitor检查复制延迟与只读状态:

-- ProxySQL 管理端执行
UPDATE global_variables SET variable_value='200' 
  WHERE variable_name='mysql-monitor_replication_lag_usecs';
UPDATE global_variables SET variable_value='1' 
  WHERE variable_name='mysql-monitor_writer_is_also_reader';

LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;

参数说明:
- mysql-monitor_replication_lag_usecs:复制延迟阈值(微秒)。超过阈值的从库会被剔除读流量。
- mysql-monitor_writer_is_also_reader:主库是否可参与读流量(建议按业务需求调整)。

配置读写分离与路由规则(示例):

-- 主机组定义:10 为写组,20 为读组
INSERT INTO mysql_servers(hostgroup_id,hostname,port,weight,comment)
VALUES
(10,'10.0.1.10',3306,100,'DC1-Writer'),
(20,'10.0.1.11',3306,100,'DC1-Reader1'),
(20,'10.0.1.12',3306,100,'DC1-Reader2');

-- 读写分离规则
INSERT INTO mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply)
VALUES
(100,1,'^SELECT.*',20,1),
(200,1,'^INSERT|^UPDATE|^DELETE|^REPLACE|^SET.*',10,1);

LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;

主库故障切换与ProxySQL刷新(示例)#

当MySQL主库故障时,提升新主库并更新ProxySQL:

# 1) 在新主库执行提升(示例:基于GTID)
mysql -uroot -p -h10.0.1.11 -e "SET GLOBAL read_only=OFF; SET GLOBAL super_read_only=OFF;"

# 2) ProxySQL中将新主库加入写组,旧主库标记为OFFLINE
mysql -uadmin -padmin -h127.0.0.1 -P6032 <<'SQL'
UPDATE mysql_servers SET status='OFFLINE_SOFT' WHERE hostgroup_id=10 AND hostname='10.0.1.10';
UPDATE mysql_servers SET hostgroup_id=10 WHERE hostname='10.0.1.11';
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
SQL

预期效果:写流量切换到新主库,旧主库不再接收写入。

灾备演练与一致性校验(示例)#

演练流程建议:主库故障 → 复制中断 → 网络分区 → 回滚/恢复。

一致性校验(PT-Table-Checksum示例):

# 在主库执行
pt-table-checksum --user=checksum --password=xxx --host=10.0.1.11 \
  --databases=appdb --replicate=appdb.checksums

# 在从库验证
mysql -uchecksum -pxxx -h10.0.1.12 -e \
"SELECT COUNT(*) AS diff FROM appdb.checksums WHERE this_cnt <> master_cnt;"

预期效果:diff=0 表示一致;非0则存在差异。

GTID一致性检查(示例):

-- 在主/从分别执行,比较GTID集合是否追齐
SHOW MASTER STATUS\G
SHOW SLAVE STATUS\G

跨机房双ProxySQL集群与配置同步(示例)#

使用ProxySQL内置复制表机制同步配置:

-- 管理端开启admin-to-admin复制(示例,需根据环境完善)
INSERT INTO proxysql_servers(hostname,port,comment)
VALUES ('10.0.2.21',6032,'proxysql02');

LOAD PROXYSQL SERVERS TO RUNTIME;
SAVE PROXYSQL SERVERS TO DISK;

说明:确保两端管理端连通,规则/主机组保持一致,避免切换时配置漂移。

排错清单(常见问题与命令)#

1) 读流量仍进入延迟从库

SELECT hostgroup_id,hostname,status,latency_us,comment 
  FROM stats_mysql_connection_pool;

检查延迟阈值与从库read_only状态。

2) 主库切换后写失败

SELECT * FROM mysql_servers WHERE hostgroup_id=10;

确认写组主机组只有新主库处于ONLINE。

3) 规则未生效

SELECT * FROM runtime_mysql_query_rules;

确认已LOAD ... TO RUNTIME

4) 配置丢失

SELECT * FROM mysql_servers;

确认已SAVE ... TO DISK

练习任务#

1) 构建一主两从MySQL复制并在ProxySQL配置读写分离,模拟从库延迟并验证延迟剔除。
2) 手动切换主库并更新ProxySQL写组,观察业务写入恢复时间(记录RTO)。
3) 使用pt-table-checksum进行一致性校验,制造一条数据差异并定位差异表。
4) 配置双ProxySQL并通过管理端复制配置,模拟切换验证规则一致性。