Appearance
高可用方案
高可用要解决的问题是:主库挂了之后,服务多快能恢复、数据会不会丢。它和备份、复制经常放在一起讨论,但三者解决的是不同层面的问题——备份管"过去的数据还在不在",复制管"数据能不能传到其他实例",高可用管"故障发生时服务能不能继续对外提供访问"。
一、单机 MySQL 的风险
| 风险 | 影响 | 单机能解决吗 |
|---|---|---|
| 主机宕机 | 所有读写请求失败 | 不能,需要冗余实例 |
| 磁盘故障 | 数据不可访问或丢失 | 不能,靠备份恢复 |
| MySQL 进程崩溃 | 连接全部断开 | 通常能自动重启,但有中断 |
| 网络隔离 | 应用访问不到数据库 | 不能,需要多实例和切换入口 |
| 误操作 | 数据被删改 | 不能,靠备份 + binlog 恢复 |
高可用主要解决的是服务可用性的问题——让故障发生后尽快恢复访问。但对于误删数据、错误更新、业务逻辑 bug 导致的数据错误,高可用不能自动修复,仍然要靠备份恢复和 binlog 回放。
二、常见方案怎么排
| 方案 | 组件 | 适合什么环境 |
|---|---|---|
| 主从 + 手工切换 | MySQL 原生复制 + 人工操作 | 小规模、可接受分钟到小时级恢复时间 |
| MHA | 传统主从自动切换 | 存量大规模主从环境,需要自动化切换 |
| Orchestrator | 拓扑管理和故障切换 | 复杂复制拓扑,需要可视化和管理能力 |
| InnoDB Cluster | Group Replication + MySQL Shell + Router | 新环境,需要官方集群方案 |
| 云厂商高可用 | 云厂商托管 | 运维负担小,但要了解云厂商高可用的具体实现细节 |
| 中间件读写分离 | ProxySQL、MyCat 等 | 读写分离 + 连接入口管理 |
选方案不只是看"能自动切换"——切换之后,应用怎么找到新主、旧主怎么处理、数据有没有丢失、回切怎么做,这些问题要全部搞清楚才算能用。
三、主从手工切换的基本流程
最基础的切换步骤:
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 明确下来,高可用方案就不会变成"尽量别挂"这种模糊的目标。