MySQL 实现读写分离:MySQL Proxy 与 mysqlnd_ms 配置教程

程一诺
程一诺
发布时间:2026-10-13 | 4人浏览过
原创

MySQL 读写分离是缓解数据库压力、提高并发处理能力的关键技术。本文通过两种常见方案——基于中间件的 MySQL Proxy 和基于 PHP 扩展的 mysqlnd_ms,详细演示了如何搭建读多写少的数据库架构,涵盖环境准备、核心配置及故障排查。

使用 MySQL Proxy 实现读写分离

MySQL Proxy 位于客户端与 MySQL 服务端之间,充当透明的连接池与过滤器。它利用灵活的 Lua 脚本分析并修改通信内容,从而实现复杂的功能,包括读写分离、负载均衡及查询过滤。对应用层而言,只需连接至 Proxy 的监听端口,而无需感知后端的具体拓扑结构。

第 1 步:安装 MySQL Proxy

推荐使用预编译的二进制包以避免复杂的依赖处理。若自行编译,需确保系统安装了 libevent (1.x)、lua (5.1.x)、pkg-config 等依赖库。

# 下载并解压二进制包(以 0.8.3 版本为例)
tar -zxvf mysql-proxy-0.8.3-linux-glibc2.3-x86-64bit.tar.gz
# 移动至指定目录
mv mysql-proxy-0.8.3-linux-glibc2.3-x86-64bit /usr/local/mysql-proxy

第 2 步:准备 MySQL 主从复制环境

读写分离的前提是已配置好 MySQL 主从同步(Master-Slave)。假设当前拓扑如下:

  • Master(主库/写): 192.168.216.133:3306
  • Slave(从库/读): 192.168.216.132:3306

第 3 步:配置 MySQL Proxy

创建配置文件 /usr/local/mysql-proxy/mysql-proxy.conf。注意:配置项的值不可添加引号。

vim /usr/local/mysql-proxy/mysql-proxy.conf

写入以下核心配置:

[mysql-proxy]
daemon=true                 # 以守护进程方式运行
keepalive=true              # 崩溃后自动重启
log-level=debug             # 调试级别日志,完成后可改为 info
log-file=/var/log/mysql-proxy.log
basedir=/usr/local/mysql-proxy
proxy-address=192.168.216.132:4040            # Proxy 对外服务端口
proxy-backend-addresses=192.168.216.133:3306  # 后端写库地址
proxy-read-only-backend-addresses=192.168.216.132:3306 # 后端读库地址
proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua # 读写分离脚本

# 管理面板配置(可选)
admin-address=192.168.216.132:4041
admin-username=admin
admin-password=admin
admin-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/admin.lua

启动时需显式加载插件:

/usr/local/mysql-proxy/bin/mysql-proxy --plugins=proxy --plugins=admin --defaults-file=mysql-proxy.conf

第 4 步:测试与管理员权限设置

启动后可登录管理端口查看状态:

mysql -u admin -padmin -h 192.168.216.132 -P 4041
SELECT * FROM backends;

初始状态下后端可能显示为 unknown,这是因为没有业务流量经过。此外,Proxy 不进行用户认证,因此必须确保后端 MySQL 允许来自 Proxy IP 的连接或授权特定账号供 Proxy 使用。如果需要自定义的管理后台功能(如返回 JSON 或特定字段),需编写 admin.lua 脚本来处理 COM_QUERY。

第 5 步:常见问题排查

  • 连接报错/日志提示 connection error: 通常是连接池阈值过小。可修改 rw-splitting.lua 中的 min_idle_connections 和 max_idle_connections,适当调大数值(如 4 和 8)。
  • 乱码问题: 检查后端 MySQL 服务器字符集配置,确保 character_set_server 与客户端一致。

使用 PHP mysqlnd_ms 模块实现读写分离

对于 PHP 项目,如果不想引入额外的中间件,可以使用 mysqlnd 的文件系统缓存与切换插件 mysqlnd_ms。该插件在服务端透明地拦截 SQL 请求,根据策略将其分发到写节点或读节点。

第 1 步:安装 mysqlnd_ms 模块

确保 PHP 已启用 mysqlnd 支持(PHP 5.3+ 默认包含)。下载源码并编译:

tar -zxvf mysqlnd_ms-1.5.2.tgz
cd mysqlnd_ms-1.5.2
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install

记录编译输出中的模块路径(例如:/usr/local/php/lib/php/extensions/no-debug-non-zts-20121212/mysqlnd_ms.so)。

第 2 步:配置 php.ini

在 php.ini 中加载扩展并指定全局配置文件:

extension = /usr/local/php/lib/php/extensions/no-debug-non-zts-20121212/mysqlnd_ms.so
mysqlnd_ms.enable = On
mysqlnd_ms.config_file = /usr/local/php/etc/mysqlnd_ms_plugin.ini

第 3 步:编写集群配置文件

创建 mysqlnd_ms_plugin.ini,定义 Master 和 Slave 列表及路由策略。以下是一个 1 主 2 从的示例:

{
 "myapp": {
   "master": {
     "master_0": {
       "host": "192.168.6.135",
       "socket": "/tmp/mysql.sock"
     }
   },
   "slave": {
     "slave_0": {
       "host": "192.168.6.136",
       "port": "3306"
     },
     "slave_1": {
       "host": "192.168.6.137",
       "port": "3306"
     },
     "filters": {
       "random": {
         "sticky": "1"  // sticky=1 保证同一次事务内读同一从库
       }
     }
   }
 }
}

参数说明: sticky: 1 表示在同一个逻辑请求/会话周期内,读取操作固定路由到某一台 Slave,避免因数据短暂延迟导致的读取不一致。

第 4 步:应用到项目中

在 PHP 代码(如 WordPress 的 wp-config.php)中连接时,不使用真实 IP,而是使用配置文件中定义的 ID 字符串:

define('DB_HOST', 'myapp'); // 对应 ini 文件中的 myapp 组名

之后所有的读写操作都会由 mysqlnd_ms 自动分流。写操作发往 master,读操作按策略轮询或随机发往 slave。

以上就是 MySQL 使用 MySQL Proxy 与 mysqlnd_ms 实现读写分离的详细内容,更多关于数据库性能优化与架构设计的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表