14.6.6 与MHA/Orchestrator的联动

在主从架构中,ProxySQL负责读写路由与连接管理,而MHA/Orchestrator负责主库故障检测与切换。两者联动的关键在于主库切换后,ProxySQL能及时感知并更新写节点与读节点列表,避免写入落到旧主或不可用节点。

原理草图(事件驱动闭环):

文章图片

联动流程要点:
- MHA/Orchestrator完成主库提升与复制链路重建,确保新主可写且从库追上。
- 切换完成后,通过事件脚本或API回调通知ProxySQL更新配置,包括mysql_servers表中的hostgroup与读写标记。
- ProxySQL自身监控与自动主库检测需与MHA/Orchestrator分工明确,避免双重决策。


安装与准备(示例环境)#

示例假设:
- ProxySQL admin 端口 6032
- 写组 hostgroup=10,读组 hostgroup=20
- Orchestrator已部署并可执行故障切换
- ProxySQL管理用户:admin:admin

安装(示例,基于Debian/Ubuntu):

# 安装 ProxySQL
sudo apt-get update
sudo apt-get install -y proxysql

# 启动服务
sudo systemctl enable --now proxysql

# 验证管理端口
mysql -uadmin -padmin -h127.0.0.1 -P6032 -e "SELECT * FROM global_variables LIMIT 1;"

准备ProxySQL后端节点(示例):

-- 登录管理端口
mysql -uadmin -padmin -h127.0.0.1 -P6032

-- 添加写组与读组
INSERT INTO mysql_servers(hostgroup_id, hostname, port, weight, max_connections, comment)
VALUES
(10, '10.0.0.11', 3306, 100, 200, 'writer'),
(20, '10.0.0.12', 3306, 100, 200, 'reader1'),
(20, '10.0.0.13', 3306, 100, 200, 'reader2');

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

事件脚本联动示例(Orchestrator WebHook)#

当Orchestrator完成切换后触发脚本,更新ProxySQL写组节点与读组成员。

脚本路径示例:/opt/orch/hooks/update_proxysql.sh

#!/usr/bin/env bash
# 参数:new_master_ip old_master_ip
NEW_MASTER="$1"
OLD_MASTER="$2"

ADMIN_USER="admin"
ADMIN_PASS="admin"
ADMIN_HOST="127.0.0.1"
ADMIN_PORT="6032"

# 将新主加入写组,旧主降级到读组或移除
mysql -u${ADMIN_USER} -p${ADMIN_PASS} -h${ADMIN_HOST} -P${ADMIN_PORT} -e "
UPDATE mysql_servers
SET hostgroup_id=10, status='ONLINE', weight=100, comment='writer'
WHERE hostname='${NEW_MASTER}';

UPDATE mysql_servers
SET hostgroup_id=20, status='ONLINE', weight=100, comment='former_master'
WHERE hostname='${OLD_MASTER}';

LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
"

echo "ProxySQL updated: new master=${NEW_MASTER}, old master=${OLD_MASTER}"

Orchestrator配置示例(WebHook触发):

{
  "PostMasterFailoverProcesses": [
    "/opt/orch/hooks/update_proxysql.sh {successor} {failedMaster}"
  ]
}

预期效果:
- ProxySQL写组(hostgroup=10)仅保留新主
- 旧主在读组(hostgroup=20)或被移除
- 应用写入自动指向新主库


管理端SQL联动示例(API驱动)#

适合中间层服务调用ProxySQL管理接口:

-- 假设新主IP 10.0.0.12 旧主IP 10.0.0.11
UPDATE mysql_servers
SET hostgroup_id=10, status='ONLINE', weight=100, comment='writer'
WHERE hostname='10.0.0.12';

UPDATE mysql_servers
SET hostgroup_id=20, status='ONLINE', weight=100, comment='former_master'
WHERE hostname='10.0.0.11';

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

关键配置关注点#

  1. 读写组划分:
SELECT hostgroup_id, hostname, status, weight, comment
FROM mysql_servers
ORDER BY hostgroup_id, hostname;
  1. 复制组关系(若使用replication hostgroups):
INSERT INTO mysql_replication_hostgroups(writer_hostgroup, reader_hostgroup, comment)
VALUES (10, 20, 'rw_split');

LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
  1. 监控用户权限最小化:
-- 在MySQL后端创建监控用户
CREATE USER 'proxymon'@'%' IDENTIFIED BY 'proxymon';
GRANT REPLICATION CLIENT, PROCESS, SELECT ON *.* TO 'proxymon'@'%';

验证与观测命令#

-- 1) 检查运行时配置生效
SELECT * FROM runtime_mysql_servers;

-- 2) 查看写组只有一个主
SELECT hostgroup_id, hostname, status
FROM runtime_mysql_servers
WHERE hostgroup_id=10;

-- 3) 路由规则
SELECT * FROM mysql_query_rules ORDER BY rule_id;

应用侧读写验证(示意):

# 写入检查(必须落到新主)
mysql -uapp -papp -hproxysql -P6033 -e "INSERT INTO test.t1 VALUES (NOW());"

# 读取检查(读组分散)
mysql -uapp -papp -hproxysql -P6033 -e "SELECT @@hostname;"

常见故障与排错#

  1. 切换后写仍落旧主
    排查:
SELECT * FROM runtime_mysql_servers WHERE hostgroup_id=10;
SELECT * FROM mysql_servers WHERE hostname='旧主IP';

处理:确保旧主在写组移除或状态设为OFFLINE_SOFT

  1. ProxySQL更新无效
    排查是否未加载运行时:
SHOW WARNINGS;
SELECT * FROM runtime_mysql_servers;

处理:执行 LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;

  1. Orchestrator钩子未执行
    排查:
sudo journalctl -u orchestrator -n 200
ls -l /opt/orch/hooks/update_proxysql.sh

处理:确认脚本可执行、参数占位符正确。


练习任务#

  1. 模拟主库故障,手动执行脚本更新ProxySQL,观察runtime_mysql_servers变化。
  2. 将旧主下线为只读,从读组移除,验证读请求是否仍可用。
  3. 修改写组权重为200/100,测试写路由是否仅落写组节点。