MySQL 5.7高可用改造:Orchestrator + ProxySQL一主三从实战
2026/9/24 19:53:14 网站建设 项目流程

先把结论写在前面:这套方案我落地过,不是从零开始搭的新系统,而是给一套已经在线上跑了好几年的 MySQL 5.7 老集群做高可用改造。数据量在 TB 级,库里有核心交易数据,业务要求“平时别动它、坏了必须快速恢复”,所以我对方案的第一个要求不是功能多炫,而是改动面小、可回滚、故障时能明确交代“数据丢了多少、多久恢复”。最终定下来的组合就是标题里写的:MySQL 5.7 一主三从,Orchestrator 负责主从切换和拓扑管理,ProxySQL 负责读写分离和流量调度。这篇文章把这套方案的选型理由、部署细节、切换链路、以及我在真实演练时踩过的几个坑完整记录下来,适合正在给存量 MySQL 5.7 做高可用改造、或者在 MHA 和 Orchestrator 之间犹豫的兄弟们参考。

1. 为什么这个场景仍然锁死 MySQL 5.7 一主三从

1.1 存量业务的现实约束

很多文章一上来就讲“新项目如何设计高可用”,但现实里大量需求是:老系统跑得好好的,数据已经积累到 TB 级,代码里又用了不少 5.7 时代的隐式转换和 SQL 写法,直接升 8.0 的风险评估做了半年也没敢动。我这次面对的就是这个情况。

先说几个硬约束:

  • 应用代码是历史遗留项目,几千条 SQL 没有全量测试覆盖,升 8.0 后认证插件、隐式排序、字符集行为都有变化,代价太大。
  • 单实例数据已经超过 1TB,迁移窗口非常紧,全量导出导入不现实。
  • 业务要求改造过程中不能长时间停机,只能通过网络层零散切换来完成。

所以“继续用 5.7,把架构升级到具备高可用能力”是唯一合理路径。MySQL 5.7 虽然已经 EOL,但它在生产环境里的稳定性和生态工具成熟度仍然够用,重点是把 5.7 的复制、GTID、半同步这些老而可靠的能力用好。

1.2 一主三从的四个节点角色划分

主从数量不是拍脑袋决定的。两从在某些场景下也够,但三从在这个项目里有非常具体的分工:

节点角色核心用途
10.0.0.11主库承担全部写流量和部分读流量
10.0.0.12从库-候选半同步复制,作为切换时的首选新主
10.0.0.13从库-报表专门给 BI 查询、统计任务用,允许慢查询
10.0.0.14从库-备份只做 xtrabackup 备份和数据校验,备份不影响线上

三个从库的用途完全不同,候选从库要保持和主库数据实时一致,报表从库可以接受秒级延迟,备份从库则故意让它承担 pt-table-checksum 这类重操作。如果只搭两个从库,切换后容错空间很窄,报表和备份就得混在一起,互相拖累。

1.3 高可用目标先量化,再谈方案

高可用不是一句“挂了自动切换”就完事。我的可量化目标是:

  • RPO 趋近 0:主库瞬间宕机时,最多丢几秒内的事务,不能接受丢 binlog。
  • RTO 60 秒内:从故障发现到业务恢复写流量,控制在 1 分钟以内。
  • 故障类别覆盖:MySQL 进程挂、宿主机宕机、网络分区三类都必须有明确应对。

这个目标直接决定了软件选型:半同步复制用于保证 RPO,Orchestrator 用于快速切换,ProxySQL 用于让应用无感知切换。三者缺一不可。

2. 方案选型:Orchestrator 和 ProxySQL 是怎么胜出的

2.1 主从切换层:MHA、keepalived、Orchestrator 三选一

在定 Orchestrator 之前,我列了三个候选:

方案优点缺点
MHA老牌、文档多、切换脚本成熟没有拓扑管理界面;故障后需要人工或额外脚本补齐从库对新主的复制关系;维护方早已停止更新
keepalived + VIP简单粗暴,VIP 漂移对网络抖动敏感,容易脑裂;MySQL 健康检测脚本要自己写,可靠性取决于脚本质量
Orchestrator自动发现拓扑、WEB UI、故障检测和切换联动机制完善搭建初期有学习成本;依赖后端元数据库

MHA 我实际用过,功能没问题,但在 TB 级一主三从上有个尴尬点:切换完成后,剩下两个从库的复制重建需要自己在脚本里写逻辑,而 Orchestrator 对“新主选出后其余从库重新指向新主”这个过程是自动完成的。keepalived 则把脑裂问题留给了应用层,我对 VIP 模式在数据库这种强一致场景下没太多信心。最终选 Orchestrator,核心原因是它把“检测、决策、执行、补偿”整个链路都接住了。

2.2 访问层:ProxySQL 为什么比 MyCat、Atlas 更合适

读写分离中间件我也对比过一轮:

  • MyCat:定位偏分库分表,规则配置重,而且它自己有状态,如果挂在 DB 前面反而成了新的单点。
  • Atlas:360 出的那个,针对 MySQL 的读写分离和分表,但项目停更多年,5.7 的新特性支持不好。
  • MaxScale:功能不错,但实际项目文档和排查经验少,遇到问题能搜到的资料太少。
  • ProxySQL:最打动我的一点是它天然就是“面向 MySQL 的流量入口”,连接池、读写分离、动态配置、SQL 路由全都有,而且是真正无状态的,前面挂 LVS 或者 F5 就可以横向扩展。

后面我会详细讲 ProxySQL 的配置,但选型阶段最关键的结论是:读写分离中间件必须能配合 Orchestrator 做“故障态联动”,而 ProxySQL 的 admin 接口和动态配置机制让这种联动很简单——切换时用脚本把主库身从 hostgroup 里换掉,LOAD TO RUNTIME 就生效,不需要重启,也不用改应用连接串。

2.3 这套组合对老库更友好的地方

很多方案喜欢把“自动切换”和“应用感知”焊死在一起,比如用 VIP 漂移让应用无感。但 TB 级老系统里,应用连接数多、连接池分散在几百台机器上,VIP 漂移之后长连接并不会自动重建,反而因为 TCP 连接断不掉导致应用卡死。

Orchestrator + ProxySQL 的思路不一样:应用连的是 ProxySQL,ProxySQL 连的是 MySQL。主库切换后,ProxySQL 用 OFFLINE_SOFT 优雅排空旧连接、把新主加入主库组,应用和 ProxySQL 之间的连接不受影响。这样改动面最小,也是老系统最需要的“带病作业”能力。

3. 一主三从落地:参数、初始化、TB 级数据追平

3.1 硬件规划和基础环境

这套环境的服务器是物理机,配置我给个参考:

  • CPU:32 核起步,如果并发写高建议 48 核以上。
  • 内存:128G,其中 InnoDB buffer pool 分配 80G 左右,剩余给系统页缓存和连接线程。
  • 磁盘:SSD 是必须的,RAID10;TB 级数据 + binlog 增长,磁盘空间至少预留数据的 1.5 倍。
  • 网络:万兆内网,因为 xtrabackup 全量同步和后续复制拉取 binlog 对带宽消耗很大。

系统层面我统一用 CentOS 7.9,MySQL 版本 5.7.44,所有节点时间用 chrony 同步,这一点容易被忽略——Orchestrator 判断复制延迟和故障时间依赖各节点时钟一致。

3.2 参数配置直接抄我这版

主库和候选从库的配置基本一致,只有 server_id 不同。关键参数如下:

[mysqld] server_id = 1 port = 3306 datadir = /data/mysql socket = /data/mysql/mysql.sock pid-file = /data/mysql/mysql.pid log_error = /data/log/mysql/error.log # InnoDB innodb_buffer_pool_size = 80G innodb_flush_log_at_trx_commit = 1 innodb_flush_method = O_DIRECT innodb_file_per_table = 1 # 二进制日志与 GTID log_bin = /data/mysql/binlog/binlog binlog_format = ROW binlog_row_image = MINIMAL sync_binlog = 1 gtid_mode = ON enforce_gtid_consistency = ON log_slave_updates = ON # 复制与半同步 skip_slave_start = 1 slave_parallel_type = LOGICAL_CLOCK slave_parallel_workers = 8 slave_preserve_commit_order = 1 rpl_semi_sync_master_enabled = 1 rpl_semi_sync_master_timeout = 1000 rpl_semi_sync_slave_enabled = 1 # 其他 character_set_server = utf8mb4 collation_server = utf8mb4_bin max_connections = 2000

几个参数值得展开说:

  • binlog_row_image = MINIMAL:只记录被修改的列,TB 级大表上能显著减少 binlog 体积和网络传输量。
  • gtid_mode = ON+enforce_gtid_consistency = ON:5.7 的 GTID 已经比较成熟,切换时不再依赖 File 和 Position 去定位,只要从库收到过这个事务就能自动追平。强烈建议 5.7 集群从第一天就把 GTID 打开。
  • slave_parallel_workers = 8:并行复制,对延迟的改善非常明显。后面我会专门说大事务场景下的延迟坑。

报表从库可以额外开long_query_time = 2slow_query_log = ON,用来抓报表同学的慢 SQL。备份从库则建议把innodb_buffer_pool_size调小一些,因为备份主要走物理读。

3.3 从库初始化:Xtrabackup 全备 + binlog 追平

TB 级数据初始化第一个从库时,绝对不能直接 mysqldump,时间太长而且会造成主库压力。我用的是 Percona XtraBackup 2.4 版本,可以和 5.7 匹配。

基本流程如下:

在备份从库上直接执行备份:

xtrabackup --backup \ --target-dir=/backup/full-bak \ --host=10.0.0.11 \ --user=backup_user \ --password=xxx \ --slave-info \ --parallel=8 \ --throttle=200

--throttle=200这个参数很关键,它限制每秒 IO 操作数,避免备份把主库磁盘 IO 打满。TB 级备份期间主库 IO 被打爆是初学者最容易犯的错。

备份完成后先做恢复准备:

xtrabackup --prepare --target-dir=/backup/full-bak

然后把数据目录 Rsync 到从库,再在从库上执行一次xtrabackup --copy-back。启动 MySQL 后,通过备份目录里的 xtrabackup_binlog_info 文件可以看到备份点对应的 binlog 文件名和位置,但在 GTID 模式下更简单,直接用:

CHANGE MASTER TO MASTER_HOST='10.0.0.11', MASTER_USER='repl', MASTER_PASSWORD='xxx', MASTER_AUTO_POSITION=1; START SLAVE; SHOW SLAVE STATUS\G

重点看Seconds_Behind_Master是否从很大的值逐渐归零。如果从库数据量已经追到非常接近主库,可以等Seconds_Behind_Master到 0 后,再做个快速校验。

3.4 追平过程中的实际体验

TB 级数据第一次初始化从库,整个过程用了大概 6 到 8 小时,其中全备约 4 小时,binlog 追平约 2 小时。期间主库的 IO 压力稳定在可控范围,业务侧没有出现明显慢查询。这个时间窗口是可以接受的。

另一个细节:初始化过程中,建议每隔 10 分钟看一次SHOW SLAVE STATUS里的Master_Log_FileRead_Master_Log_Pos,确认拉取 binlog 的速度能跟上主库生成速度。如果一直拉不平,大概率是网络带宽瓶颈,而不是 MySQL 配置问题。

4. Orchestrator 接入与自动切换:核心配置与原理

4.1 安装和基础配置

我这里用的是 Orchestrator 3.2.6,直接下载二进制包解压部署。需要注意两点:

第一,Orchestrator 自身需要一个后端元数据库,存储拓扑信息和故障检测记录。这个库规模很小,可以单独建一个 MySQL 实例,也可以复用集群里的某个节点,但建议独立创建,不要和业务库混在一起。

第二,Orchestrator 需要一个账号来探测所有 MySQL 实例,权限如下:

GRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD, SELECT ON *.* TO 'orc'@'10.0.0.%' IDENTIFIED BY 'xxx';

如果希望 Orchestrator 通过SHOW SLAVE HOSTS自动发现拓扑,还需要REPLICATION CLIENT权限。这里有个容易漏的点:需要给 Orchestrator 后端元数据库也单独建一个账号,权限只需要 SELECT、INSERT、UPDATE、DELETE、CREATE、ALTER。

核心配置文件 orchestrator.conf.json 里我重点改了这些:

{ "Debug": false, "ListenAddress": ":3000", "MySQLTopologyUser": "orc", "MySQLTopologyPassword": "xxx", "BackendDB": { "Host": "10.0.0.10", "Port": 3306, "User": "orc_backend", "Password": "xxx", "Database": "orchestrator" }, "DefaultInstancePort": 3306, "DiscoverByShowSlaveHosts": true, "InstancePollSeconds": 5, "DetectClusterAliasQuery": "SELECT CONCAT('cluster-', @@port)", "DetachLostSlavesAfterSeconds": 30, "RecoveryPeriodBlockSeconds": 60, "FailMasterPromotionOnExpiredGtid": true, "PostFailoverProcesses": [ "/opt/scripts/update_proxysql_after_failover.sh" ] }

几个参数解释:

  • InstancePollSeconds = 5:每 5 秒探测一次实例。这个值和 RTO 直接相关,如果你把 RTO 目标定在 30 秒内,探测间隔就不能大于 10 秒。
  • DetachLostSlavesAfterSeconds = 30:故障发生 30 秒后,仍然找不到 master 的从库会被标记为 detached,避免它们在错误的状态下继续复制。
  • FailMasterPromotionOnExpiredGtid = true:如果选中的新主存在缺失的 GTID 事务,则放弃提升,避免因为数据空洞造成新的不一致。这个必须开,尤其在有半同步和异步混合的场景下。

4.2 手动切换演练:graceful-master-takeover

Orchestrator 装好后会自动拉取拓扑,登录 WEB UI 能看到 10.0.0.11 为主、三个从库挂在下面。做计划内切换时用命令行:

orchestrator-client -c graceful-master-takeover -alias cluster-3306

Orchestrator 会自动完成这些事:

  1. 把主库设为只读。
  2. 等待所有从库追上最新 GTID。
  3. 从候选从库中选出延迟最低、数据最全的那个,提升为新主。
  4. 其余从库自动 CHANGE MASTER 指向新主,使用 MASTER_AUTO_POSITION=1。
  5. 触发 PostFailoverProcesses 里的脚本。

整个过程在数量级上比 MHA 的脚本可控性高很多,MHA 做完切换后还得自己手动调整其他从库的复制链路。

4.3 自动切换链路和误判规避

自动切换的链路是:探测超时 → 进入故障检测流程 → 判定 master 是否真的不可用 → 触发恢复 → 选择新主 → 重搭复制 → 调用外部脚本。

这里最容易出问题的是误判。网络抖动导致 Orchestrator 连着几次 ping 不到主库,就会触发切换,而这个切换在业务高峰期代价很大。我做了三个防御:

  • 探测网段和管理网段分离,Orchestrator 通过独立管理网访问数据库节点,避免业务高峰网络拥塞影响探测。
  • RecoveryPeriodBlockSeconds = 60:同一集群故障恢复后 60 秒内不会再次自动切换,防止“切换刚落定又被误判”的二次抖动。
  • 维护窗口内手动设置 Orchestrator 维护模式,告诉它“这是计划内操作,不要干预”。

维护模式用下面这个命令:

orchestrator-client -c begin-maintenance -i 10.0.0.11:3306 --reason="planning switchover"

操作结束后再 end-maintenance 释放。这个机制在做索引重建、大事务提交前尤其有用,避免 Orchestrator 因为主库暂时“响应慢”误以为是故障。

4.4 切换后其他从库的一致性处理

还有一个容易被忽略的点:切换完成后,原来的主库如果只是宕机恢复,它重新上线时会尝试连接新的主库继续复制。如果新主上多了很多它没有的事务,Orchestrator 会基于 GTID 自动尽量追平,但它会明确标记这个节点为“lagg”状态。对于原来那台主库,我更建议直接把它降级为普通从库,让它从备份节点拿一次全量重搭复制链路,不要尝试让它保留旧数据继续跑。

5. ProxySQL 读写分离与故障态切换联动

5.1 ProxySQL 的三层配置模型

ProxySQL 的配置分三层:runtime(当前生效)、memory(内存查询)、disk(持久化),任何修改都要显式执行 LOAD 和 SAVE 才会依次生效。第一次配置的人容易漏掉LOAD ... TO RUNTIME导致改了不生效,然后一顿排查,其实问题就在这。

装好 ProxySQL 后用 admin 接口连入:

mysql -uadmin -padmin -h127.0.0.1 -P6032 --prompt='ProxySQL> '

5.2 后端实例和 hostgroup 规划

ProxySQL 的逻辑核心是 hostgroup。我规划了 0 组为主库组,1 组为从库组。

插入后端节点:

INSERT INTO mysql_servers (hostgroup_id, hostname, port, status, weight, max_connections) VALUES (0, '10.0.0.11', 3306, 'ONLINE', 100, 2000), (1, '10.0.0.12', 3306, 'ONLINE', 100, 1000), (1, '10.0.0.13', 3306, 'ONLINE', 100, 1000), (1, '10.0.0.14', 3306, 'ONLINE', 100, 800);

注意我暂时没把主库加到从库组。实际中是否让主库承担读取决于读多还是写多。我这个场景写并发高,主库的 IO 已经比较饱和,所以从库组只放三个从库。

5.3 读写分离规则:别把 FOR UPDATE 路由到从库

查询路由规则是 ProxySQL 最核心的部分。我的规则大致如下:

INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES -- (1, 1, '^SELECT.*FOR UPDATE', 0, 1) 这样写不完善,看下面完整版 ;

实际推荐用多条件组合,先把写语句和锁定读匹配出来:

INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (1, 1, '^SELECT .* FOR UPDATE', 0, 1), (2, 1, '^SELECT ', 1, 1), (3, 1, '^SHOW ', 1, 1), (4, 1, '^UPDATE |^INSERT |^DELETE ', 0, 1);

这里有几个坑:

  • SELECT ... FOR UPDATE必须在纯 SELECT 规则之前匹配,否则会被当成普通读分摊到从库。这个是最经典的线上事故。
  • ProxySQL 的规则匹配基于正则,^SELECT不会匹配(SELECT或带前缀的语句,联表子查询里可能漏。建议对慢查询日志和 ProxySQL stats 里的语句做一轮验证,确认没有查询被错误路由。
  • 如果应用有事务内“读后写”的场景,必须设置规则让事务里的所有语句保持在同一主机上执行。也就是在 mysql_users 表里为对应用户开启:
UPDATE mysql_users SET transaction_persistent=1 WHERE username='app_user';

这个参数很关键:事务内第一条语句命中了哪个 hostgroup,后续整个事务都走同一个节点,否则会出现“在从库读到了旧数据,回主库去更新”的错乱。

5.4 创建应用用户

ProxySQL 对外暴露的用户名和密码可以跟 MySQL 不同,但转发到后端时必须映射真实账号。

INSERT INTO mysql_users (username, password, default_hostgroup, transaction_persistent, max_connections) VALUES ('app_user', 'app_pass', 0, 1, 500);

注意default_hostgroup=0,这样没有规则匹配的语句默认走主库,宁慢勿错。

5.5 和 Orchestrator 的切换联动脚本

现在还差最后一块:Orchestrator 切换完成后,如何让 ProxySQL 知道“主库变了”。

我的方案是在 orchestrador 的PostFailoverProcesses里挂一个脚本,切换时自动更新 ProxySQL 的 hostgroup 配置。脚本核心逻辑如下:

#!/bin/bash NEW_MASTER_HOST="$1" NEW_MASTER_PORT="$2" OLD_MASTER_HOST="$3" OLD_MASTER_PORT="$4" PROXYSQL_ADMIN="mysql -uadmin -padmin -h127.0.0.1 -P6032 -Nse" $PROXYSQL_ADMIN "REPLACE INTO mysql_servers (hostgroup_id, hostname, port, status, weight, max_connections) VALUES (0, '${NEW_MASTER_HOST}', ${NEW_MASTER_PORT}, 'ONLINE', 100, 2000);" $PROXYSQL_ADMIN "UPDATE mysql_servers SET status='OFFLINE_SOFT' WHERE hostgroup_id=0 AND hostname='${OLD_MASTER_HOST}' AND port=${OLD_MASTER_PORT};" $PROXYSQL_ADMIN "LOAD MYSQL SERVERS TO RUNTIME;" $PROXYSQL_ADMIN "SAVE MYSQL SERVERS TO DISK;"

这个脚本的巧妙之处在于OFFLINE_SOFT状态:ProxySQL 会立刻停止向旧主库发送新请求,但已经建立的连接会继续保留直到事务完成或连接自然断开。相比 OFFLINE_HARD(直接杀连接),应用无感程度高得多。

为了安全,脚本里我加了一步校验:先确认新主库真的能连接,再执行上面的操作,参数用 Orchestrator 传入的前两个位置。实际跑下来,从 Orchestrator 触发到 ProxySQL 完成切换,耗时不超过 3 秒。

6. 切换演练与长期维护的几个提醒

6.1 演练一:计划内割接

所有配置上线后,第一件事不是祈祷它不坏,而是主动做一次计划内切换,验证整条链路。我的操作顺序:

  1. 提前通知业务方进入维护窗口。
  2. 给 Orchestrator 设置 begin-maintenance,计划内操作手动执行。
  3. 执行 graceful-master-takeover。
  4. 观察 ProxySQL 是否自动把新主加入主库组、旧主是否被置为 OFFLINE_SOFT。
  5. 执行一轮读写检查,确认 SELECT 到了从库、INSERT/UPDATE 到了新主。
  6. 二次切换,切回原主库,确认整个链路是可逆的。

我实测的 RTO 从发起到写流量恢复大约 45 秒,其中 20 秒花在 Orchestrator 等从库追上 GTID、10 秒花在 ProxySQL 动态更新 hostgroup,其余是探测时间。

6.2 演练二:模拟主库进程崩溃

计划内验证完,还要模拟真正的故障。我把主库实例直接kill -9,观察 Orchestrator 的表现:

  • 第 5 秒:探测失败。
  • 第 15 秒:触发故障检测,发现主库不可达。
  • 第 25 秒:完成新主提升和数据补偿检查。
  • 第 35 秒:ProxySQL 联动脚本执行完毕,写流量切到新主。
  • 应用报错窗口:约 20 秒内,少量写请求失败,需要应用层重试。

这个结果基本满足当初定义的 RTO 目标。但演练也暴露了一个问题:由于主库配置是半同步rpl_semi_sync_master_timeout=1000,在极端情况下半同步会退化成异步,极端宕机可能丢掉最后 1 秒内的数据。所以我又额外加了 relay log 的保留策略,确保候选从库尽量多保留中继日志,减少数据丢失概率。

6.3 TB 级场景下的几个长期维护提醒

大事务延迟。TB 级表上跑一个UPDATE ... WHERE扫全表的事务,会产生巨大的 binlog,从库就算开了并行复制也容易落后。我踩过一次:凌晨一个报表任务 DELETE 老数据,扫了 30 分钟,三个从库 Seconds_Behind_Master 全部冲到几千秒。后来规定所有大变更必须用 pt-osc 或 gh-ost,且禁止生产从库直接执行大范围 DML。

复制延迟不能只看 Seconds_Behind_Master。这个指标在某些情况下会失真,尤其从库 IO 线程堆积时。我的做法是额外建一张心跳表,主库每秒更新,从库每 5 秒查一次,用两边的当前时间差估算真实延迟。比自带指标可靠得多。

定期数据校验。TB 级集群跑了一段时间后,最怕静默的数据不一致。我每周在备份从库上跑一次 pt-table-checksum:

pt-table-checksum \ h=10.0.0.14,u=checksum_user,p=xxx \ --databases=core_db \ --replicate=pt.checksums \ --chunk-size=1000 \ --max-lag=3 \ --throttle=50

然后对比三个从库的 checksum 是否有差异。如果发现不一致,再用 pt-table-sync 修复。注意这几个命令本身会占用资源,必须放在备份从库上跑,不要在候选从库上跑。

6.4 应用层配合高可用改造的几个点

这套架构搭完了,如果应用层不配合,切换时照样会出问题。我在改造时给开发团队提了几条要求,其实也适合所有高可用场景:

  • 连接池要配置最大生命周期,建议 10 到 30 分钟,确保切换后不再依赖旧连接。
  • 写请求失败要有重试机制,但必须做幂等控制,否则一次超时重试可能导致重复下单。
  • “写完立刻读”的业务,要么走主库,要么接受短时间不一致。建议在 SQL 前缀加注释让 ProxySQL 强制走主库,比如/*master*/ SELECT ...,规则里匹配^/\*master\*/路由到 0 组。
  • 应用侧不要尝试连具体 MySQL 节点 IP,统一走 ProxySQL 对外地址,这样高可用对应用才真正透明。

6.5 最终经验总结

这套 Orchestrator + ProxySQL 方案上线后运行时间已经不短,整体非常稳。真正遇到过的生产问题反而是配置层面的小坑,比如 ProxySQL 规则匹配漏掉了FOR UPDATE、Orchestrator 维护模式忘关导致后续切换被阻断、备份从库磁盘空间不足导致 xtrabackup 失败。这些坑单看都不难,但组合在一起会在故障时放大处理难度。

最后分享一个实操技巧:切换脚本里除了更新 hostgroup,我还会往 ProxySQL 的 mysql_servers 里写入当前主库的注释信息,并同步写一份到/tmp/failover_history.log,记录每次切换的时间、发起原因、新旧主节点。故障复盘和追溯时,这些日志比任何监控截图都值钱。

如果你正准备给存量 MySQL 5.7 上高可用,我的建议是不要急着看新特性,先把“数据不丢、切换快、能回溯”这三件事做扎实。这套方案可能不是最炫的,但对于 TB 级老系统来说,它是真正能让你在凌晨 3 点接到告警电话时还能保持冷静的方案。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询