数据库中间件mysql-proxy细节【mysql官方的中间件】

article/2025/10/6 5:48:06

一、mysql-proxy简介

mysql-proxy是mysql官方提供的mysql中间件服务,上游可接入若干个mysql-client,后端可连接若干个mysql-server,它使用mysql协议,任何连接mysql的上游无需任何更改即可迁移至mysql-proxy上。

mysql-proxy最基本的用法,就是作为一个请求拦截,请求中转的中间层:

进一步的,mysql-proxy可以分析与修改请求。拦截查询和修改结果,需要通过编写Lua脚本来完成。mysql-proxy允许用户指定Lua脚本对请求进行拦截,对请求进行分析与修改,它还允许用户指定Lua脚本对服务器的返回结果进行修改,加入一些结果集或者去除一些结果集均可。

【SK画外音:sql拦截与修改,性能分析与监控,读写分离,请求路由等各种功能都是通过编写Lua脚本来完成的,mysql-proxy是个框架,具备很好的扩展性。这个框架提供了6个hook点,能够让用户能够动态的介入到client与server中的通讯中去。】

二、mysql-proxy命令参数

版本显示

使用--version参数即可:

./mysql-proxy --version

从输出可以看到mysql-proxy的版本,以及依赖的glib,libevent,lua的版本

1 mysql-proxy0.8.3

2 chassis: mysql-proxy 0.8.3

3 glib2: 2.16.6

4 libevent: 1.4.13-stable

5 LUA: Lua 5.1.4

8 -- modules

9 proxy: 0.8.3

简单启动

mysql-proxy启动至少需要指定一个后端mysql的ip和端口号,此时带上--proxy-backend-addresses参数即可:

./mysql-proxy --proxy-backend-addresses=127.0.0.1:3306

指定配置文件启动

mysql-proxy亦可以指定配置文件启动,此时带上--defaults-file来指定配置文件即可:

./mysql-proxy --defaults-file=./mysql-proxy.cnf

mysql-proxy.cnf的格式如下:

1[mysql-proxy]

2proxy-backend-addresses = 127.0.0.1:3306

需要注意,在命令行中参数前需要加入“--”,而在配置文件中则不需要。

寻求帮助

可以使用--help,或者--help-all

./mysql-proxy --help

./mysql-proxy --help-all

Proxy常用选项

选项

说明

proxy-backend-addresses=$host:$port

后端mysql的ip和port,多个以逗号分隔

proxy-read-only-backend-addresses=$host:$port

后端只读mysql的ip和port,多个以逗号分隔

proxy-skip-profiling=$bool

是否禁用查询性能剖析

proxy-lua-script=$file_name

lua文件

注意:

如果设置了多个后端mysql,负载均衡策略为round-robin。例如设了A和B两台后端,第一个请求转发到A,第二个请求转发到B,第三个请求转发到A,以此类推。

Proxy服务常用选项

选项

说明

proxy-address=$host:$port

mysql-proxy的ip和port,默认port是4040

daemon=$bool

是否使用daemon模式启动

event-threads=$count

event-handing线程数,默认值是1

keep-alive=$bool

proxy服务崩溃后自动重启

log-file=$file_name

日志文件

log-level=$level

日志级别:error|warning|info|message|debug

log-use-syslog=$bool

日志使用syslog

max-open-files=$count

最大文件句柄数

pid-file=$file_name

pid文件

典型配置文件示例

1[mysql-proxy]

2

3proxy-address = 127.0.0.1:4040

4 daemon =true

5event-threads = 2

6 keep-alive= true

7 log-file =./mysql-proxy.log

8 log-level= debug

9max-open-files = 1024

10 pid-file =./mysql-proxy.pid

11

12 proxy-lua-script= ./ro-balance.lua

13proxy-backend-addresses = 127.0.0.1:3306

14proxy-skip-profiling = false

启动过程中提示:

2013-12-28 15:15:49: (critical)mysql-proxy-cli.c:326: loading config from './mysql-proxy.cnf' failed:permissions of ./mysql-proxy.cnf aren't secure (0660 or stricter required)

由于安全要求,必须将配置文件权限设为660(创建人可读写,同组人可读),否则不允许启动。

三、mysql-proxy脚本编程

如“简介”中所述,mysql-proxy向用户提供了6个hook点,让用户实现Lua脚本来完成各种功能,这些hook点是以函数的形式提供的,用户可以实现这些函数,在不同事件、不同操作发生时,做我们期望的事情。

connect_server()

mysql-client向proxy发起连接时,proxy会调用这个函数。用户可以实现该函数,来做一些负载均衡的事情,例如选择将要连向那个mysql-server。假设有多个mysql-server后端,而用户又没有实现这个函数,proxy默认采用轮询(round-robin)策略。

read_handshake()

mysql-server向proxy返回“初始握手信息”时,proxy会调用这个函数。用户可以实现这个函数,来做更多的权限验证工作。

read_auth()

mysql-client向proxy发送认证报文(user_name, password,database)时,proxy会调用这个函数。

read_auth_result()

mysql-server向proxy返回认证结果时,proxy会调用这个函数。

read_query()

认证完成后,mysql-client每次经过proxy向mysql-server发送query报文时,proxy会调用这个函数。用户如果要拦截请求,就可以模拟mysql-server直接返回了,当然用户亦可以实现各种策略,修改请求,路由请求等各种不同的业务逻辑。

read_query_result()

认证完成后,mysql-server每次经过proxy向mysql-client返回query结果时,proxy会调用这个函数。需要注意,如果用户没有显示实现read_query()函数,则read_query_result()函数是不会被调用的。用户可以在此处实现各种合并策略,或者对结果集进行修改。

【SK画外音:下图是一个各hook函数的触发图(请注意请求方向)】

【SK继续画外音:可以发现,最重要的两个函数其实是read_query()和read_query_result(),各种sql的改写与结果集的改写逻辑,都是在这两个函数中实现的,更细节的query过程如下图】

案例一: sql时间统计分析

不妨设mysql-client提交的原sql为:SELECT * FROM City;

proxy可以在read_query()里将其改写为:SELECT NOW(); SELECT *FROM City; SELECT NOW();

这样在返回结果集时,就可以在应用层对sql时间进行记录,以方便统计分析。

案例二:sql性能统计分析

不妨设mysql-client提交的原sql为:SELECT * FROM City;

proxy可以在read_query()里将其改写为: SELECT * FROM City; EXPLAIN SELECT * FROMCity;

这样在返回结果集时,就可以在应用层对sql性能进行记录,以方便统计分析。

需要强调的是,这两个案例,由于proxy在read_query()时对sql进行了改写,故在read_query_result()时,mysql-server其实返回了比原请求更多的信息,proxy一定要将多余的信息去掉,再返回mysql-client。多说一句,可以加入一个唯一ID,来对请求sql和返回结果进行配对。

demo

需求:在业务层统计sql日志

实现:tutorial-basic.lua

1 -- 如果是COM_QUERY,就将内容打印出来

2 functionread_query( packet )

3 if string.byte(packet) == proxy.COM_QUERYthen

4 print("we got a normal query:" .. string.sub(packet, 2))

5 end

6 end

修改配置并重启proxy:

proxy-lua-script = tutorial-basic.lua

客户端使用黑黑的窗口连接4040端口的proxy,并进行一系列sql操作,操作序列如下:

mysql -h127.0.0.1 -uroot -P4040

show databases;

use im;

show tables;

select * from user;

quit

通过tutorial-basic.lua,会将上述操作都记录到日志中,日志序列如下:

we got a normal query: select @@version_comment limit1

we got a normal query: show databases

we got a normal query: SELECT DATABASE()

we got a normal query: show tables

we got a normal query: select * from user

【SK画外音:咦,通过这个日志我才知道,连上数据库会默认发一个select @@version_comment limit 1的请求呢。use im;这个请求,为啥变成SELECT DATABASE()了呢?】

四、FAQ

(1)如何实现最简单的读写分离?

shell> mysql-proxy \

--proxy-backend-addresses=10.0.1.2:3306 \

--proxy-read-only-backend-addresses=10.0.1.3:3306

(2)mysql proxy支持所有版本的mysql么?

只支持mysql5.0+的mysql协议。

(3)如果开启负载均衡,那事务怎么办?所有的query会发往同一台mysql么?

如果用户不专门定制Lua脚本,会发往同一台mysql,以保证其完整性。

(4)系统上下文切换代价大么?Lua脚本引入的额外开销有多大?

Lua很快,对于大部分应用来说,额外开销很小,原始包(raw packet)开销大概在400微秒左右。

【SK画外音:这,,,我不太相信】

(5)Lua脚本可以动态加载么?

升级了Lua脚本,连接建立后才会读取新的哟。

(6)如果proxy和mysql部署在一台机器上,有什么需要建议的呢?

proxy单独部署也可以,和mysql部署在同一台机器上也可以。相比mysql而言,proxy不怎么占CPU和内存,其性能损耗可以忽略不计。

【SK画外音:这,,,性能损耗可以忽略,这我也不信】

(7)Lua脚本是预读到内存里的吧?还是说每次都要到文件系统里读?

客户端连接过来时,或者脚本更新时会读取,其他的时候都读内存哟。

(8)加入客户端连上来,出发了connect_server()函数,Lua脚本能连接多个mysql么?

可以,使用指引里有样例代码哟。

(9)proxy可以处理SSL连接么?

不可以,作为中间人,不能处理加密信息。

(10)proxy不会获取和保存我的明文密码吧?

不会,也获取不到。mysql协议不允许密码以明文传输,传输的都是加密后的密文。

(11)有隔离问题,调试问题的工具么?如果请求出错了,我怎么知道错误发生在mysql客户端,还是mysql服务端,还是proxy呢?

你可以自己在proxy里设置debug脚本进行调试,例如设置断点什么的。

(12)瞧你官网吹的,有哪个大网站用了mysql-proxy么?请求量是什么级别?

这问题问的,作为官网我,,,盖亚在线(http://www.gaiaonline.com/) 就是用的mysql-proxy哟,qps可以到2400。

【SK画外音:这是个外国的游戏网站,页面好丑啊。】

(13)如果我在Lua脚本用使用LuaSocket可以么?

大哥,这可能引起阻塞的,强烈不建议这样。

都读到这了,帮忙随手转发一个呗,原创不易。

下一期,将介绍阿里的数据库中间件。

回复大于10的随机整数,自动获取随机好文。


http://chatgpt.dhexx.cn/article/t1r6XhgL.shtml

相关文章

数据库中间件概述

1.为什么需要数据库中间件,何为数据库中间件 不同的应用程序有不同的数据存储方式和组网。数据量小的普通的应用程序一般采用单机数据库来持久化数据,如下图。 当数据的并发读写超过数据库服务器的处理能力时,需要进行读写分离来分离读写压力…

数据库访问中间件

数据库访问中间件 什么是ORM框架 对象关系映射(Obiect Relational Mapping,简称ORM),用于实现面向对象编程语言里不同类型系统的数据之间的转换。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的…

MySQL中间件Atlas

MySQL中间件Atlas atlas简介 Mysql 的 proxy 中间件有比较多的工具,例如,mysql-proxy(官方提供), atlas , cobar, mycat, tddl, tinnydbrouter等等。 而Atlas是由 Qihoo 360公司Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它在…

【MySQL】数据库(分库分表)中间件对比

分区:对业务透明,分区只不过把存放数据的文件分成了许多小块,例如mysql中的一张表对应三个文件.MYD,MYI,frm。 根据一定的规则把数据文件(MYD)和索引文件(MYI)进行了分割,分区后的表呢,还是一张…

数据库中间件详解

数据库中间件详解 原创: 田守枝 田守枝的技术博客 3月24日 1 数据库拆分过程及挑战 互联网当下的数据库拆分过程基本遵循的顺序是:垂直拆分、读写分离、分库分表(水平拆分)。每个拆分过程都能解决业务上的一些问题,但同时也面临了一些挑战。…

mysql优化---如何搭建mysql的主从关系和mycat中间件

1. 如何搭建mysql的主从关系 解决mysql高并发的瓶颈。 1.1 复制概述 复制是指将主数据库的DDL 和 DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。 MySQ…

什么是中间件

一、什么是中间件 中间件(Middleware)是处于操作系统和应用程序之间的软件,也有人认为它应该属于操作系统中的一部分。人们在使用中间件时,往往是一组中间件集成在一起,构成一个平台(包括开发平台和运行平…

mysql的中间件比较

mysql分布式数据库中间件对比 目前数据库中间件有很多,基本这些中间件在下都有了解和使用,各种中间件优缺点及使用场景也都有些心的。所以总结一个关于中间件比较的系列,希望可以对大家有帮助。 1. 什么是中间件 传统的架构模式就是 应用连…

MySQL 中间件汇总比较

360 Atlas 较为活跃,Atlas 是由 360 Web平台部基础架构团队开发维护的一个基于 MySQL 协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用 Atlas 运行的 MySQL 务,每…

MySQL-中间件mycat(一)

目录 🍁mycat基础概念 🍁Mycat安装部署 🍃初始环境 🍃测试环境 🍃下载安装 🍃修改配置文件 🍃启动mycat 🍃测试连接 🦐博客主页:大虾好吃吗的博客 &#x1f9…

MySQL 分表方案及中间件介绍

背景 什么情况下需要分表?这里归纳了3点: (1)某个表被操作的频率过于频繁的时候(可以查看某个表的访问频繁),在流量越来越大的时,可以考虑分表。 (2)某个表的数据量过于庞大的时候(我给自己设…

中间件之MYSQL

体系结构 server层 负责建立连接、分析和执行 SQL 连接器:与客户端进行TCP三次握手;校验用户名和密码;读取权限。查询缓存:key-value缓存在mysql8.0后默认将其关闭;高级版本默认采用页缓存。解析器:词法…

mysql优化——mycat数据库中间件

文章目录 目录 文章目录 前言 一、mycat原理 二、mycat完成读写分离 2.1搭建MySQL的主从模式 2.2实现读写分离 三、mycat垂直分库 四、水平分表 五、水平拆分表的连表操作 六、全局表 总结 前言 Mycat是数据库中间件,所谓中间件,是一类连接软件组件和应用的计算机软件,以…

mysql中间件汇总

一、写在前面 mysql作为互联网公司都会用到的数据库,在使用过程中。会用主从复制来提高性能。会用分库分表解决写入问题。以下介绍mysql中间件的一些实现方案 二、Atlas Atlas时 360 公司开发维护的一个基于MySQL协议的数据中间层项目。 2.1 atlas架构 Atlas是一…

makfile的编译选项:CFLAGS、CPPFLAGS、LDFLAGS、LIBS

1、LDFLAGS & LIBS 关于makefile的依赖规则以及目标生成的步骤,这篇先不介绍,这里主要关注我在看makefile时遇到的一堆CFLAGS与LDFLAGS定义进行说明。 费了牛劲,才查到GNUmake中文手册中关于CFLAGS与LDFLAGS的说明,他们都是…

Makefile 编译与链接选项及CFLAGS与LDFLAGS说明

CFLAGS与LDFLAGS的说明,他们都是是隐含规则的变量,且是一种命令参数变量. makefile内嵌隐含规则的命令中,所使用的变量都是预定义的变量。我们将这些变量称为“隐含变量”。这些变量允许对它进行修改:在Makefile中、通…

Go新项目-项目添加版本说明,以及参数传递:ldflags、gcflags,外加stripped说明(5)

在Go项目中,会存在展示该项目的版本信息,以及打包日期,项目版本,Go版本等;继Go新项目-编译项目的细节(4)以后再记录下编译优化方向,刚好也有项目版本输出的需求。 关键词&#xff1…

linux编译参数CPPFLAGS、CFLAGS、LDFLAGS参数的理解

参考到下面博客,把编译步骤分解的很细 linuxC编译参数CPPFLAGS、CFLAGS、LDFLAGS参数的理解 - yongfengnice - 博客园 CPPFLAGS : 预处理器需要的选项 如:-I (大写i指定头文件路径) CFLAGS:编译的时候使用的参数 –Wall –g -c LDFLAGS &…

【Java位运算】异或运算的使用

异或运算有个特性:两个相同的数做异或运算,结果为0。 n ^ n 0;常用的方式是查找数组中只出现一次的数字。 例如:在一个数组中,只有一个数字出现了一次,其余数字都出现了两次。 求这个数字。利用异或运算的特性进行计…

java中与运算,或运算,异或运算

Java的位运算符详解实例——与(&)、非(~)、或(|)、异或(^) 位运算符主要针对二进制,它包括了:“与”、“非”、“或”、“异或”。从表面上看似乎有点像逻…