Appearance
高可用方案
高可用要解决的问题是:主库挂了之后,服务多快能恢复、数据会不会丢。它和备份、复制经常放在一起讨论,但三者解决的是不同层面的问题——备份管"过去的数据还在不在",复制管"数据能不能传到其他实例",高可用管"故障发生时服务能不能继续对外提供访问"。
一、单机风险
单机 MySQL 面临的风险:主机宕机(所有读写请求失败,需要冗余实例)、磁盘故障(数据不可访问或丢失,靠备份恢复)、MySQL 进程崩溃(连接全部断开,通常能自动重启但有中断)、网络隔离(应用访问不到数据库,需要多实例和切换入口)、误操作(数据被删改,靠备份 + binlog 恢复)。
高可用主要解决的是服务可用性的问题——让故障发生后尽快恢复访问。但对于误删数据、错误更新、业务逻辑 bug 导致的数据错误,高可用不能自动修复,仍然要靠备份恢复和 binlog 回放。别指望高可用能救命所有问题。
二、方案选型
| 方案 | 组件 | 适合什么环境 |
|---|---|---|
| 主从 + 手工切换 | MySQL 原生复制 + 人工操作 | 小规模、可接受分钟到小时级恢复时间 |
| MHA | 传统主从自动切换 | 存量大规模主从环境,需要自动化切换 |
| Orchestrator | 拓扑管理和故障切换 | 复杂复制拓扑,需要可视化和管理能力 |
| InnoDB Cluster | Group Replication + MySQL Shell + Router | 新环境,需要官方集群方案 |
| 云厂商高可用 | 云厂商托管 | 运维负担小,但要了解云厂商高可用的具体实现细节 |
| 中间件读写分离 | ProxySQL、MyCat 等 | 读写分离 + 连接入口管理 |
选方案不只是看"能自动切换"——切换之后,应用怎么找到新主、旧主怎么处理、数据有没有丢失、回切怎么做,这些问题要全部搞清楚才算能用。光看个 demo 演示觉得能自动切换就上,真出事时一堆细节没想过。
三、主从手工切换
最基础的切换步骤:
text
1. 确认主库不可用或需要主动下线
2. 在所有从库里选延迟最小、数据最全的那台
3. 停止这个从库的复制,确认不再从旧主接收变更
4. 关闭只读,宣布新主
5. 修改应用连接入口(VIP/DNS/配置中心)
6. 其他从库改挂新主
7. 旧主恢复后以从库身份加入核心 SQL 操作:
sql
-- 在要提升的从库上执行
STOP REPLICA;
RESET REPLICA ALL;
SET GLOBAL read_only = OFF;
SET GLOBAL super_read_only = OFF;sql
-- 在其他从库上执行,改挂新主
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='10.0.0.20', -- 新主库 IP
SOURCE_PORT=3306,
SOURCE_USER='repl',
SOURCE_PASSWORD='ReplPassword_123!',
SOURCE_AUTO_POSITION=1;
START REPLICA;手工切换在小规模环境可行,但要有清晰的 SOP。故障中临时想步骤,容易把旧主、新主、各个从库的状态搞乱。至少把"选主标准"和"提升新主的命令序列"提前写好,故障时照着执行,别现场发挥。
四、切换确认事项
主从切换不是"把新主提起来"就算完成,还有三件事必须确认:
| 确认事项 | 具体检查 | 为什么不能漏 |
|---|---|---|
| 新主是不是最新 | GTID 已执行集合、主从延迟、和其他从库对比 | 提了一个数据落后的从库,切换后数据永久不一致 |
| 旧主不会继续写 | 网络隔离、只读状态、VIP/入口是否已移走 | 双主写入是恢复起来最麻烦的一类问题 |
| 应用真的恢复了 | 写接口、读接口、连接池重建、错误率 | 数据库能连不等于业务能正常运转 |
新主确认:
sql
SELECT @@read_only, @@super_read_only; -- 必须是 OFF,否则写不进去
SHOW MASTER STATUS; -- 确认 binlog 状态正常主从延迟没有收敛时强行提升,主库上最近的提交可能还没到新主——这就是数据缺口。判断能不能切的依据是 Seconds_Behind_Source 和 GTID 集合差异,而不是"看起来差不多了"。凭感觉切的,十有八九会丢数据。
五、读写分离
text
写请求 → 主库
读请求 → 从库读写分离提高了读的扩展能力,但引入了一个根本问题:复制延迟。刚写到主库的数据,去从库马上读,可能还没同步过来。
处理延迟的几种方式各有取舍:关键路径读主(写完后立刻要读到最新结果的请求发给主库,代价是主库读压力增加)、延迟过大摘除从库(落后太多的从库从读列表里移除,代价是剩余从库分摊更多读)、会话粘滞(同一会话的写和读走同一实例,需要中间件或应用支持)、业务容忍(允许读到几秒前的旧数据,看业务能不能接受)。
读写分离不是加越多从库越好。从库增多 → 复制链路增多 → 延迟监控、故障摘除都更复杂。每加一个从库都要确认:它能不能扛住分配的读流量,延迟够不够低。
六、半同步复制
异步复制不等待从库确认,主库宕机时最后一部分事务可能丢失。半同步复制要求至少一个从库确认收到日志后,主库才返回提交成功:
sql
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';
SET GLOBAL rpl_semi_sync_source_enabled = ON;
SET GLOBAL rpl_semi_sync_replica_enabled = ON;半同步提升了数据安全性——已提交事务至少已经到了一个从库的 relay log 里。但代价是:如果从库或网络异常,主库提交被卡住,可能会退化成异步(依赖超时参数设置)。它保证的是"至少一个从库收到了日志",不等于"从库已经完成 SQL 回放"——所以延迟仍然要监控。
七、应用连接入口
切换新主后,应用怎么找到新地址,几种方式各有优缺点:VIP 漂移对应用透明切换也快,但依赖网络环境支持 VIP;DNS 切解析简单通用,但 TTL 和连接池缓存可能导致切过去后旧地址还连着;代理层路由可以做健康检查、读写分离和连接池,但代理自身也需要高可用,否则是单点;配置中心动态刷新控制灵活,但应用要支持动态刷新连接配置。
DNS 切换不只是改解析记录。很多数据库连接池创建后不会主动重新解析 DNS——它们会一直连着旧 IP 直到连接被断开或超时重建。所以 DNS 切换后还要观察连接数分布,确认流量真的切走了——这又是个容易被忽略的坑。
八、数据一致性检查
主从延迟不等同于数据不一致——延迟只是"回放还没到那个位点"。真正的数据不一致是指:同样的行在主从上有不同的值。可能因为:跳过过某个复制事务、直接写了从库、复制错误被忽略。
用工具检查:
bash
pt-table-checksum \
--host=10.0.0.10 \
--user=checksum \
--password='ChecksumPassword_123!' \
--replicate=percona.checksums它在主库上把每张表分成小块,对每块算校验和,写入 percona.checksums 表并复制到从库。从库上再对同样的块算校验和,和主库对比。发现差异后用 pt-table-sync 修复,但同步修复语句生成后需人工审查,确认不会覆盖合法的新数据。
一致性检查会消耗 CPU 和 IO,大库要放在低峰运行。
九、故障演练
"故障时会自动切换"如果没有经过实际验证,就不算可依赖的高可用。
演练内容:
| 演练场景 | 观察什么 |
|---|---|
| kill 主库 MySQL 进程 | 是否正确检测到故障,是否完成切换,耗时多久 |
| 断开主库网络 | 是否误判、是否出现脑裂(旧主仍以为自己是主) |
| 从库延迟很大 | 是否跳过落后节点、是否阻止切换 |
| 旧主恢复 | 是否自动重新加入、是否需要人工处理 |
| 应用连接切换 | 是否自动重连、错误率和延迟变化 |
演练记录不但要保留,还要有具体数字:
text
演练时间:
故障注入方式:
检测耗时:从故障发生到系统检测到的用时
切换耗时:从检测到开始切换到新主可写的用时
应用恢复时间:从切换完成到应用恢复正常处理请求的用时
是否丢数据:
人工介入点:
遗留问题:光记一句"演练成功"等于没演练,真出事时这些数字才是复盘和改进的依据。
十、RTO 与 RPO
高可用方案最终落到两个指标:
| 指标 | 含义 | 决定什么 |
|---|---|---|
| RTO | 从故障到服务恢复需要多久 | 自动化程度、切换入口设计、演练频率 |
| RPO | 最多能接受丢多少数据 | 复制方式(异步/半同步)、binlog 刷盘策略 |
业务能接受的 RTO 和 RPO 直接决定了架构取舍。如果 RPO=0(不能丢任何已提交事务),异步复制就不够,要用半同步甚至强一致方案;如果 RTO=30 秒,手工切换基本不可能,必须上自动切换;如果 RTO=4 小时,人工操作空间就大很多。
不是所有系统都需要最严格的 RTO/RPO——按业务实际需求分级,核心交易系统用强一致方案,报表和分析库可以接受异步复制和较长恢复时间。把每个库的 RTO/RPO 明确下来,高可用方案就不会变成"尽量别挂"这种模糊的目标——有了具体数字,该投入多少、用什么方案,就有清晰的判断依据。