做MySQL运维的朋友,迟早会碰到一个绕不开的话题:数据库代理(Proxy)。业务量一旦上来,主库写压力高、从库读流量分配不均、主从切换要改一堆应用连接串,这些问题会逼着你去找一个能统一收口的中间层。MaxScale就在这种情况下进入我的视野——它是MariaDB官方出品的MySQL/MariaDB代理,能帮忙承担读写分离、负载均衡、自动故障转移和查询路由。这篇指南我按一条真实上线路径来写:先讲清楚为什么需要它、部署前要想什么,再给一套可直接套用的配置,接着拆解路由和监控的底层逻辑,最后分享上线后踩过的坑以及maxctrl日常巡检方法。不管你是刚接触MySQL的新人,还是正在做代理选型的DBA,应该都能从里面找到自己需要的那部分。
1. 先从选型说起:为什么是MaxScale,而不是另一套代理
1.1 没有代理层之前,我经历过的三个痛点
最早维护一套单主双从的MySQL集群时,我的日常可以用三个词概括:改配置、等发布、背锅。业务线直接在配置中心里写下多个从库地址,从库扩容时要挨个通知应用方修改连接串;某个从库宕机后,监控明明红了,但应用里的连接池还在向这个死亡地址发起新连接,直到超时重试才缓缓反应过来。主从切换更是一场灾难,手动把从库提升为主库后,还需要在配置中心里改一大圈读写地址,期间整个联调环境都处于不可用状态。
换句话讲,应用层直接面向MySQL裸连接,是把架构的脆弱性暴露给了所有上游。我当时的诉求很明确:有一个统一入口,应用只配一个地址,读写路由由入口负责,主从切换时入口能自动感知并处理。这个诉求指向的正是数据库代理层。
理论上也可以自己在应用里封装一套多数据源路由,Java有现成的sharding-jdbc、读写分离插件,Go也有各种方案。但问题是,公司里不同团队语言不统一、维护成本高,一旦有人把事务和读路由的关系搞错,线上故障就来了。代理层的价值在于:把路由逻辑从业务代码里抽出来,收口到基础设施层,让应用只关心连一个地址。
1.2 MaxScale、ProxySQL、MySQL Router、MyCat的定位差异
选型阶段我把市面主流方案都过了一遍。MySQL Router是MySQL官方出品的轻量路由,配置简单但功能偏少,不太适合做复杂路由和故障转移;ProxySQL功能确实很强,查询规则、缓存、流量控制都有,但配置体系比较重,规则写多了之后排查起来累;MyCat更偏向分库分表,一旦引入就相当于把整个数据访问层都交给它,改造量大。相比之下,MaxScale走的是“聚焦读写分离和高可用”的路线,配置结构清晰,和MySQL/MariaDB的复制体系贴合得很紧,内置的monitor直接管理主从感知、failover、rejoin,不需要额外写脚本。
我当时用一个小型压测环境简单对比过,下面这张表基本说明了差异:
| 方案 | 读写分离 | 自动故障转移 | 配置复杂度 | 分库分表能力 | 我对它的评价 |
|---|---|---|---|---|---|
| MaxScale | 成熟 | 内置,和复制状态联动 | 较低,一个conf文件即核心 | 不支持,专注路由层 | 读写分离和高可用组合场景最优 |
| ProxySQL | 成熟 | 依赖外部脚本或ProxySQL Admin配置 | 高,规则和库表多 | 不支持 | 适合对查询规则有极强定制需求的人 |
| MySQL Router | 基础 | 依赖InnoDB Cluster元数据 | 低 | 不支持 | 轻量场景够用,复杂拓扑别指望 |
| MyCat | 有 | 较弱 | 高 | 支持 | 分库分表场景才会考虑 |
如果你和我一样,核心痛点就是“读写分离不彻底、主从切换太痛苦”,MaxScale是投入产出比最高的一款。它不需要改造业务SQL,不需要引入分片键,部署形态也足够简单。
1.3 什么场景不适合用MaxScale
选型教育了我一件事:没有万能组件,先想清楚它解决不了什么,再决定要不要用它。
MaxScale解决的是路由和读写分发,不解决数据容量问题。如果单库数据量已经到几个T且还在暴涨,需要的是拆库拆表,MaxScale这个层级帮不上忙,它不是分布式数据库中间件,不会帮你做分片计算。另外,它也不负责修复主从复制本身的故障,如果binlog损坏、延迟持续追不上,MaxScale能做的只是把那个从库标记为Down或限制它参与路由,真正修复复制链路还是得靠DBA自己。还有一个容易被忽略的点:MaxScale本身有网络转发成本,如果业务对延迟极其敏感,每个查询都多一跳代理会产生毫秒级损耗,这种场景下需要权衡是否值得。
你会看到,MaxScale擅长的是把复杂多变的主从拓扑封装成一个稳定入口,让应用侧变简单。这正好是业务量上升期团队最需要的。
2. 部署前必须做的三件事:拓扑、账号与版本
2.1 推荐的最小生产拓扑长什么样
很多人一上来就装MaxScale,结果发现文档里讲了一堆概念,反而不知道从哪开始。我建议部署前先在纸上画清楚拓扑。这里给一个最小但完整的生产参考:
[应用服务] -> [VIP: 10.0.0.10] | [MaxScale A] [MaxScale B] <- 代理层,可做双机 \ / [MySQL Master] [MySQL Slave1] | [MySQL Slave2]如果团队规模不大,可以先用一台MaxScale跑起来,等稳定了再引入Keepalived或MaxScale自身的多机方案做VIP漂移。关键点是MaxScale不要和MySQL部署在同一个宿主机上,否则宿主机宕机时代理和后端数据库一起离开,整个入口就彻底没了。
2.2 先确认后端主从复制本身是健康的
MaxScale的monitor模块很强大,但它只负责“观察”复制状态,不负责“建立”复制关系。如果你后端的主从复制本身就有问题,MaxScale配置得再完美也只是把问题曝光得更明显。
在部署MaxScale前,我建议先完成这些基本功:每台MySQL的server_id全局唯一,log_bin开启,gtid_mode=ON(MySQL 8建议开启,MariaDB 10.11之后也推荐),从库的read_only打开,复制账号已经建好并确认SHOW REPLICA STATUS里没有报错。只有主从复制链路本身稳定,MaxScale基于复制状态做failover才有意义,否则它会以为某个节点是健康的,结果数据在主从间根本对不上。
2.3 MaxScale专用账号的权限设计与创建SQL
MaxScale和MySQL之间需要两类账号:一类是监控账号,monitor模块用它去连接每台后端服务器,检测主从状态、计算延迟、判断节点角色;另一类是路由账号,service在处理客户端连接时会用它去向后端发起真正的数据库连接。实际配置里二者可以共用一个账号,但建议分开,权限更好控制。
下面这套SQL适用于MySQL 8.x和MariaDB,直接抄即可:
CREATE USER 'maxscale_monitor'@'%' IDENTIFIED BY 'M0nitor@Passw0rd'; GRANT SELECT ON mysql.user TO 'maxscale_monitor'@'%'; GRANT SELECT ON mysql.db TO 'maxscale_monitor'@'%'; GRANT SELECT ON mysql.tables_priv TO 'maxscale_monitor'@'%'; GRANT SELECT ON mysql.roles_mapping TO 'maxscale_monitor'@'%'; GRANT SHOW DATABASES ON *.* TO 'maxscale_monitor'@'%'; GRANT REPLICATION CLIENT ON *.* TO 'maxscale_monitor'@'%'; GRANT REPLICATION SLAVE ON *.* TO 'maxscale_monitor'@'%'; CREATE USER 'maxscale_route'@'%' IDENTIFIED BY 'R0ute@Passw0rd'; GRANT SELECT ON *.* TO 'maxscale_route'@'%'; GRANT INSERT ON *.* TO 'maxscale_route'@'%'; GRANT UPDATE ON *.* TO 'maxscale_route'@'%'; GRANT DELETE ON *.* TO 'maxscale_route'@'%'; GRANT SHOW DATABASES ON *.* TO 'maxscale_route'@'%';不推荐给路由账号配超级权限。REPLICATION CLIENT这个权限很关键,MaxScale需要它来读取复制状态;如果没有这个权限,从库的复制健康度会读不出来,节点可能被误判为Down。mysql.user和相关系统表的SELECT权限则用于检查后端账号是否存在、当前账号的权限元数据,权限缺失时MaxScale日志里会不断刷“permission denied”的告警。
这里要额外提醒一点:如果你后端是MySQL 8.0,默认认证插件是caching_sha2_password,旧版本的MaxScale对它的支持不稳定。稳妥做法是在MySQL 8上建maxscale专用账号时显式指定mysql_native_password:
CREATE USER 'maxscale_monitor'@'%' IDENTIFIED WITH mysql_native_password BY 'M0nitor@Passw0rd';新版MaxScale已经兼容caching_sha2_password,但如果你用的是老版本,还是建议用这个方式避免连接认证报错。
2.4 版本选择与安装方式
MaxScale的版本史比较有意思,早期是独立版本号6.x、7.x,后来跟着MariaDB的节奏切到了23.x、24.x。无论哪个时期,6.4都是一个相当稳定的版本,线上有一批老集群还在用它;新项目我建议直接用24.x,配置语法变化不大,官方文档也更完整。
安装方式上,主流操作系统都可以从MariaDB官方源直接安装。RedHat/CentOS系:
curl -Ls https://rpm.mariadb.com/maxscale/24.2/rhel/9/x86_64/maxscale-24.2.1-1.rhel.9.x86_64.rpm -o maxscale.rpm yum install -y maxscale.rpmDebian/Ubuntu系:
curl -Ls https://deb.mariadb.com/maxscale/24.2/ubuntu/pool/main/m/maxscale/maxscale-24.2.1-1.ubuntu.22.04.jammy_amd64.deb -o maxscale.deb apt install -y ./maxscale.deb实际上版本号一直在更新,上面URL里的具体包名会变化,最保险的方式是访问MaxScale官方下载站,选择对应系统和架构的rpm或deb包。安装完成后,二进制路径通常在/usr/bin/maxscale,配置文件在/etc/maxscale.cnf,日志在/var/log/maxscale/maxscale.log。如果使用Docker部署,注意把/var/lib/maxscale目录持久化,不然容器重启后监控数据和管理账号信息会丢失,这个坑后面单独展开。
3. 从一份最小配置到真正跑通读写分离
3.1 先理解MaxScale的四个核心对象
刚开始看MaxScale文档,容易被listener、service、monitor、server这些词绕晕。我用一个餐厅的类比帮助理解:
- server:后厨的灶台,对应每台MySQL实例。
- service:配餐规则,决定“哪些菜去哪个灶台炒”,比如读走A灶台、写走B灶台。
- listener:餐厅门口的接客窗口,对应应用连接的IP和端口。
- monitor:巡查员,每隔几秒去看每个灶台是否还在正常运转、哪口锅是主灶。
一个MaxScale进程可以配置多个service、多个listener、多个monitor,但最小可用的配置只需要一套。
3.2 最小可用配置文件
用vim打开/etc/maxscale.cnf,写入下面这段配置:
[maxscale] threads=auto admin_host=127.0.0.1 admin_port=8989 admin_user=maxadmin admin_password=Admin@123 [server1] type=server address=192.168.10.11 port=3306 protocol=MariaDBBackend [server2] type=server address=192.168.10.12 port=3306 protocol=MariaDBBackend [MySQL-Monitor] type=monitor module=mariadbmon servers=server1,server2 user=maxscale_monitor password=M0nitor@Passw0rd monitor_interval=1000 failover=1 auto_rejoin=1 [Read-Write-Service] type=service router=readwritesplit servers=server1,server2 user=maxscale_route password=R0ute@Passw0rd master_accept_reads=true [Read-Write-Listener] type=listener service=Read-Write-Service protocol=MariaDBClient address=0.0.0.0 port=4006说几个关键字段:
module=mariadbmon是MaxScale 6.x以后的监控模块名,旧文档里mysqlmon已经废弃。monitor_interval=1000表示每1秒巡检一次。对普通业务够用,对高可用要求更高的场景可以调到500,但会增加监控账号的连接压力。failover=1开启自动主从切换。首次启动时我建议先设成0,手动验证一切正常后再打开,避免误判导致自动切库。master_accept_reads=true允许主库参与读路由。主库性能宽裕时开着能分摊读压力;如果主库已经是写瓶颈,把它设成false,所有读尽量走从库。
3.3 启动MaxScale并验证读写分离
安装完成后注册成系统服务:
systemctl start maxscale systemctl enable maxscale启动后用maxctrl list servers看节点状态:
maxctrl list servers正常情况下你会看到类似这样的输出:server1的State是Master, Running,server2的State是Slave, Running。如果显示Down,先回头看密码和权限是不是给错了,这是90%启动失败的原因。
然后从应用视角连一次MaxScale的4006端口:
mysql -h 192.168.10.10 -P 4006 -uapp_user -p进去后执行:
SELECT @@server_id;多开几个会话执行几次,你会发现@@server_id在多个节点间变化,说明读流量已经被分发到不同后端。要验证写路由是否走主库,可以开一个事务执行SELECT,然后看连接始终绑定在同一个节点上。不要指望单条查询就能看到完美的轮流分发,MaxScale的后端连接池会影响复现,多开几个并发连接体验更明显。
3.4 从“最小配置”到“生产配置”缺少的几块拼图
最小配置能跑通,但离生产可用还差几步。failover=1虽然开了,但原主库恢复后是否自动重新加入集群,靠的是auto_rejoin=1。生产上还需要考虑客户端连接上限、从库延迟阈值、大查询隔离等,这些在后面章节展开。总之先把链路跑通,再逐步调优,别一上来就堆满全部参数。
4. 路由、连接与故障转移的底层逻辑
4.1 SELECT不等于一定走从库
这是我见过最多的误解:以为配置了读写分离,所有SELECT就一定会去从库。实际不是。
readwritesplit路由器的判断逻辑是“语句类型 + 上下文状态”。一个客户端如果开启事务(BEGIN或autocommit=0),事务里的所有语句都会被固定到同一节点,避免跨节点读到不一致数据。也就是说,事务里第一个语句是SELECT,那这个SELECT可能就落在主库上。如果你的应用框架(比如某些ORM默认开启事务)把大量查询包在事务里,结果就是所有读流量全部打在主库,从库闲置,主库压满。遇到这种情况,我先建议去查业务代码里是不是把无关的读操作也塞进了事务。
还有几类语句也会被强制发往主库:SELECT ... FOR UPDATE,涉及存储函数、临时表、GET_LOCK()等有状态操作的语句。另外,会话级别变量一旦被SET修改,后续语句为了保持一致性也会留在主库。代理能识别语法,但无法判断你的存储函数是否“纯读”,所以它选择了保守策略。
4.2 从库选择策略:LEAST_CURRENT_OPERATIONS还是LEAST_ROUTER_CONNECTIONS
当多个从库都可用时,MaxScale如何挑选目标?配置项slave_selection_criteria控制这个逻辑。默认值是LEAST_ROUTER_CONNECTIONS,意思是从后端连接池中选当前活跃连接数最少的节点,策略偏向“连接均衡”。另一选项是LEAST_CURRENT_OPERATIONS,偏向“正在执行的语句数最少”,能更快避开瞬时大查询带来的卡顿。
我在实践中发现,LEAST_CURRENT_OPERATIONS更能反映节点真实繁忙程度,因为它统计的是正在执行的SQL操作数,而连接数多不代表每个连接都在跑大SQL。配置里加上这一行:
[Read-Write-Service] type=service router=readwritesplit servers=server1,server2 slave_selection_criteria=LEAST_CURRENT_OPERATIONS如果某台从库复制延迟明显高于其他节点,可以设置max_slave_replication_lag(单位秒),超过阈值的从库会被自动移出路由候选池,避免读到滞后太久的旧数据。
4.3 应用连接池、MaxScale会话、后端连接池三者之间的关系
这是连接问题排查中最容易绕晕的地方。连接链路上实际上有三层:应用层连接池、MaxScale会话、MaxScale与MySQL之间的后端连接。
应用层连接池管理的是“客户端到MaxScale”的连接;MaxScale会为每个客户端会话维持一条会话上下文,但当多个客户端会话都指向同一个后端节点时,MaxScale可以选择让它们共享后端连接,这就是它自带的连接复用能力。换句话说,应用侧开500个连接,后端MySQL不一定真的建500个连接,MaxScale会按需复用,有效降低MySQL端的连接压力。
但这不代表应用侧可以无限开连接。MaxScale的每个客户端连接仍然要消耗文件描述符和内存,如果业务侧把maximum-pool-size设成几千,单机MaxScale一样会被打穿。建议应用连接池设计遵循两个原则:一是压测后确定合理上限,而不是随手填一个很大的值;二是连接空闲超时要和MaxScale侧的不一致错开,避免互相踩踏导致连接提前被回收。
4.4 主库宕机时,MaxScale到底做了什么
主库故障的完整流程值得每个DBA刻在脑子里,因为业务感知到的就是“连接闪断了一下”,但背后的动作其实很多:
- monitor在下一个巡检周期(默认1秒)发现主库连接异常或复制状态中断,将该节点标记为
Down。 - 当
failover=1时,mariadbmon依据master_priority配置或复制拓扑信息,从健康从库中选举一个新主。 - MaxScale将新主标记为
Master,后续新事务全部路由到新主。 - 已经被故障主库承载的旧连接会中断,应用侧需要重试。
- 如果
auto_rejoin=1,原主库恢复后会被配置成新主的从库,自动沿着binlog或GTID追数据,追平后重新标记为Slave, Running。
这个过程中最影响体验的是第4步。应用侧如果没有重试机制,一次切换就会造成成批报错。所以在生产环境里,我一直强调:MaxScale做好故障转移只是前提,应用层连接池必须配置短超时+快速重试,这样用户才能无感知。
5. 业务接入阶段最容易翻车的连接问题
5.1 应用账号必须在后端每台服务器上同时存在
MaxScale本身不存储业务数据,它把客户端连接“翻译”到后端MySQL时,用的是你这个业务账号在后端执行SQL。也就是说,应用连接MaxScale时用的app_user,必须已经在server1、server2等所有后端MySQL上都创建好了,且权限一致。
我曾经在接入阶段遇到一个诡异现象:连MaxScale后查询正常,但某些页面偶尔报1045 Access denied。最后排查发现,新扩容的一台从库上忘了建app_user,MaxScale把读请求路由到这台从库时后端拒绝了认证。解决方案很简单:把账号创建SQL在所有后端节点都执行一遍,或者用配置管理工具统一下发数据库账号,避免只在其中一台机器上建。
5.2 从库read_only不一致带来的隐患
MaxScale通过monitor读取每个节点的角色,决定谁是Master谁是Slave。假如某台从库忘了设置read_only=1,尽管它名义上是Slave,但实际上仍然可以写。一旦应用被路由到这个从库执行写入,数据就会在主从之间出现分叉,且这种分叉不会自动修复,最终只能手动重建该从库。
所以从库一定要统一加上:
SET GLOBAL read_only = ON; SET GLOBAL super_read_only = ON;其中super_read_only在MySQL 8里能防止具有SUPER权限的账号写入,保护性更强。这个经验说出来不值钱,但生产环境的从库漏配read_only的真实案例多到数不清,尤其是大批量初始化从库时脚本少执行了一次。
5.3 连接断开的恢复路径:应用层重试设计
不管MaxScale的故障转移做得多么顺滑,主库宕机的那一瞬间,旧连接一定是失效的。Java的MySQL Connector/J有一个autoReconnect=true参数,但它只对“连接空闲后重建”有效,如果正在执行事务时连接断开,这个参数不会救你,反而可能让你误以为应用能自动恢复。
更可靠的做法是在应用的数据访问层加一层快速重试:捕获连接异常后,短暂sleep,然后重新从连接池获取连接、重发之前失败的语句。重试次数不宜多,2到3次即可,重试间隔建议100毫秒左右,因为MaxScale完成failover通常在1到3秒内,如果重试批次太密集,反而会叠加成对MaxScale的连接风暴。
6. 上线后我们追过的三类MaxScale疑难杂症
6.1 一个从库延迟“吃掉”整个读流量
有次业务反馈高峰期查询变慢,我查MaxScale却看到两个从库都处于Running状态,但实际只有一台从库在承担读流量。原因是那台健康的从库发生了严重复制延迟,MaxScale按照默认策略虽然没把它剔除,可新连接都在蜂拥往另一台从库上挤,最终把那个从库也压垮了。
排查后我把max_slave_replication_lag=5加进了service配置,延迟超过5秒的从库自动从路由池摘除。这就好比配餐时只让上菜快的后厨参与出餐,慢的灶台先暂停接单。加了这个参数后,读流量在多从库间的分配明显均衡了。
[Read-Write-Service] type=service router=readwritesplit servers=server1,server2,server3 max_slave_replication_lag=56.2 认证插件不兼容导致MaxScale连不上MySQL 8
新项目搭了一套MySQL 8.0.32,把MaxScale和它接好之后,日志里持续出现“Unable to authenticate”的报错。一开始以为是密码错,反复验证无误后才发现问题出在认证插件上。
MySQL 8默认的caching_sha2_password要求连接双方都支持对应的认证流程,老版本MaxScale对这种认证的支持并不完整。解决方式有两个方向:升级MaxScale到支持caching_sha2_password的新版本;或者在不出问题的前提下,给MaxScale专用账号指定mysql_native_password。考虑到老集群里的MaxScale版本不好动,我当时用的是第二种方式,新建账号时显式指定认证插件,问题立刻消失。
6.3 大查询淹没了某个从库
报表团队的几个同事喜欢直接连从库在线跑大查询,一遍GROUP BY跑上几分钟,直接影响线上读路由。MaxScale本身不会帮你区分“这是报表查询还是业务查询”,它能做的就是把路由规则定清楚。
我的做法是给报表类场景单独开一条通道:拿一台或几台从库单独组成一个新的service,监听不同的端口,比如4007,专供离线查询使用;4006端口留给线上业务。这样大查询再猛,也只影响报表通道,不会拖垮线上读流量。顺便说一句,如果你在某个查询前面加/* maxscale route to master */这样的注释,MaxScale会识别并把它路由到主库,这是一条内置的hint路由,适合偶尔需要强制走主库的场景。
6.4 Docker部署MaxScale时要注意的目录和数据持久化
现在不少团队习惯用Docker起中间件,MaxScale也提供了官方镜像。直接docker run虽然能跑起来,但有个问题:容器销毁后,/var/lib/maxscale里的数据会丢,包括之前配置产生的监控缓存、管理口令、以及部分持久化状态。结果就是重启后认证状态异常,甚至admin账号失效。
用Docker部署时一定把配置目录、日志目录、数据目录都挂到宿主机物理路径上:
docker run -d \ --name maxscale \ -p 4006:4006 \ -p 8989:8989 \ -v /etc/maxscale.cnf:/etc/maxscale.cnf \ -v /var/lib/maxscale:/var/lib/maxscale \ -v /var/log/maxscale:/var/log/maxscale \ mariadb/maxscale:24.2另外容器里通常不会自动启动systemd,所以要用docker run的方式托管,而不是在容器里执行systemctl start maxscale。这个操作层面的差异,容易让第一次用Docker的人卡住半天。
7. 日常巡检三板斧:maxctrl、REST API与日志
7.1 每天上班先看的三个maxctrl命令
MaxScale上线后,日常巡检不需要天天登到MySQL里看复制状态,用maxctrl会更高效。我每天的习惯是先跑三个命令:
maxctrl list servers maxctrl show services maxctrl list sessionslist servers看每台后端节点的State,重点关注有没有节点变成Down,以及主从角色是否符合预期。show services看路由服务的整体连接数、路由统计,如果连接数比平时高出一截,说明可能有应用侧连接泄漏。list sessions列出当前客户端会话,遇到问题时要看有没有哪台客户端占着大量会话不释放。
这三个命令的输出很短,但信息密度极大,基本覆盖了“节点健康、路由状态、会话状态”三个关键维度。建议写个小脚本封装成一条命令,每天早晨跑一遍。
7.2 用REST API把MaxScale接进监控平台
MaxScale自带REST API,默认监听在admin_port,也就是8989端口。公司有统一监控平台的,可以直接把MaxScale的指标接进去。简单验证一下API是否可用:
curl -u maxadmin:Admin@123 http://127.0.0.1:8989/v1/servers/返回的JSON里包含每个server的state、connections、replication lag等字段。我一般会重点采集节点状态和复制延迟两个指标,一旦state不是期望的角色就告警。对接Prometheus类平台的话还可以用现成的exporter,不过直接用REST API拉也一样,省去额外组件。
7.3 日志里报“replication is broken”时先别急着删server
有段时间MaxScale日志里频繁出现“Replica is broken”的告警,第一反应是这台从库的复制链路坏了。但我登录MySQL看SHOW REPLICA STATUS,复制却是正常的。后来才明白,MaxScale的mariadbmon对复制断开的判定条件是多个维度组合,包括半同步状态、GTID位置是否持续推进、监控账号读复制状态的权限是否足够,某个维度异常就会误报。
遇到报错不要急着用maxctrl destroy server把节点移除,先按顺序排查:监控账号的权限是否完整、后端MySQL的read_only和复制状态是否正常、GTID是否持续更新。如果这些都没问题,再把monitor_interval适当调大,观察是否还继续误报。我调过一次后,日志瞬间安静了。
7.4 在测试环境强制演练故障,比看十遍文档都管用
最后说一个个人习惯:我会每隔一段时间在测试环境强制kill掉主库进程,观察MaxScale是否在预期时间内完成failover、从库是否自动提升、原主库恢复后是否能重新加入。这套演练做下来,maxctrl的常用命令基本就烂熟于心了。真正到生产故障时,肌肉记忆比临时翻文档可靠得多。MaxScale的价值只有在“真的出过事”之后才能体会,而提前演练,就是给自己吃定心丸的最好方式。