ProxySQL是基于MySQL协议开发的高性能中间件,支持连接池、查询路由、读写分离、故障转移等多种功能,在MySQL集群架构中常被用作流量入口,将读请求和写请求分发到不同的后端MySQL实例,从而提升数据库的整体处理能力。

环境准备
在开始配置之前,需要先准备好以下环境:
- 一台独立的服务器用于部署ProxySQL,建议配置2核4G及以上资源
- 至少两台MySQL实例,一台作为主库(处理写请求),一台作为从库(处理读请求),主从复制已经配置完成且正常运行
- ProxySQL安装包,本文以ProxySQL 2.4.4版本为例,系统环境为CentOS 7
安装ProxySQL
首先通过官方仓库安装ProxySQL,执行以下命令:
# 添加ProxySQL官方仓库 cat <<EOF | tee /etc/yum.repos.d/proxysql.repo [proxysql_repo] name=ProxySQL YUM repository baseurl=https://repo.proxysql.com/ProxySQL/proxysql-2.4.x/centos/7 gpgcheck=0 enabled=1 EOF # 安装ProxySQL yum install proxysql -y # 启动ProxySQL并设置开机自启 systemctl start proxysql systemctl enable proxysql
配置ProxySQL实现读写分离
ProxySQL的配置分为运行时配置和持久化配置,修改配置后需要先加载到运行时,再保存到磁盘持久化。首先通过管理端口登录ProxySQL,默认管理端口是6032,用户名和密码都是admin:
mysql -u admin -padmin -h 127.0.0.1 -P 6032
添加后端MySQL实例
将MySQL主库和从库添加到mysql_servers表中,其中hostgroup_id用于区分实例角色,1代表写组,2代表读组:
-- 添加主库到写组 INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight, comment) VALUES (1, '192.168.0.10', 3306, 100, 'mysql_master'); -- 添加从库到读组 INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight, comment) VALUES (2, '192.168.0.11', 3306, 100, 'mysql_slave'); -- 加载配置到运行时并持久化 LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;
配置监控用户
ProxySQL需要监控后端MySQL实例的状态,因此需要先在MySQL主库上创建一个监控用户:
-- 在MySQL主库执行,创建监控用户 CREATE USER 'proxysql_monitor'@'192.168.0.%' IDENTIFIED BY 'monitor_pass'; GRANT USAGE ON *.* TO 'proxysql_monitor'@'192.168.0.%'; FLUSH PRIVILEGES;
然后在ProxySQL中配置监控用户信息:
-- 设置监控用户和密码 UPDATE global_variables SET variable_value='proxysql_monitor' WHERE variable_name='mysql-monitor_username'; UPDATE global_variables SET variable_value='monitor_pass' WHERE variable_name='mysql-monitor_password'; -- 加载变量配置到运行时并持久化 LOAD MYSQL VARIABLES TO RUNTIME; SAVE MYSQL VARIABLES TO DISK;
配置读写分离规则
通过mysql_query_rules表配置查询路由规则,将写请求路由到写组,读请求路由到读组:
-- 写请求规则,匹配所有非SELECT开头的SQL,路由到hostgroup 1 INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES (1, 1, '^(?!SELECT)', 1, 1); -- 读请求规则,匹配所有SELECT开头的SQL,路由到hostgroup 2 INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES (2, 1, '^SELECT', 2, 1); -- 加载规则到运行时并持久化 LOAD MYSQL QUERY RULES TO RUNTIME; SAVE MYSQL QUERY RULES TO DISK;
配置客户端访问用户
添加客户端连接ProxySQL时使用的用户,该用户需要映射到后端MySQL的用户:
-- 添加客户端用户,default_hostgroup指定默认路由的组,这里默认走写组
INSERT INTO mysql_users (username, password, default_hostgroup, transaction_persistent)
VALUES ('app_user', 'app_pass', 1, 1);
-- 加载用户配置到运行时并持久化
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
验证读写分离效果
使用客户端用户连接ProxySQL的默认业务端口6033,执行相关SQL验证路由是否生效:
# 连接ProxySQL业务端口 mysql -u app_user -papp_pass -h 127.0.0.1 -P 6033
登录后执行写操作,查看请求是否路由到主库:
-- 执行建表语句
CREATE DATABASE test_db;
USE test_db;
CREATE TABLE user_info (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20));
-- 执行插入语句
INSERT INTO user_info (name) VALUES ('test_user');
然后执行读操作,查看请求是否路由到从库:
-- 执行查询语句 SELECT * FROM user_info;
可以通过ProxySQL的stats_mysql_query_digest表查看请求路由情况:
-- 在ProxySQL管理端口执行,查看请求统计 SELECT hostgroup, digest_text, count_star FROM stats_mysql_query_digest WHERE digest_text LIKE '%%user_info%%';
注意事项
- 主从复制延迟可能会导致读请求获取到旧数据,需要根据业务场景设置合理的读从库的阈值,或者将强一致性的读请求路由到主库
- ProxySQL的查询规则匹配是基于正则的,需要根据实际业务SQL的特点调整规则,避免路由错误
- 定期查看ProxySQL的监控日志,及时发现后端MySQL实例的故障,ProxySQL会自动将故障实例从可用列表中移除
- 如果业务中有事务操作,建议开启
transaction_persistent参数,避免同一个事务中的请求被路由到不同的实例