数据库中间件mysql-proxy细节
一、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可以么?
大哥,这可能引起阻塞的,强烈不建议这样。
数据库中间件mysql-proxy细节相关推荐
- mysql proxy集群_数据库集群中间件MySQL Proxy探讨
数据库集群中间件 MySQL Proxy 探讨 杨芳萍 ; 马宏艳 ; 王斌 [期刊名称] <电子制作> [年 ( 卷 ), 期] 2013(000)019 [摘要] 互联网高速发展的同时 ...
- 数据库中间件支持数据库集群方案
咏南数据库中间件支持数据库集群方案 通过咏南数据库中间件作为PROXY(数据库代理)实现的数据库集群,非数据库层面集群. 数据库可以分库分表进行水平或垂直拆分成数据库集群. 咏南中间件作为数据库集群代 ...
- mysql分布式数据库中间件对比
目前数据库中间件有很多,基本这些中间件在下都有了解和使用,各种中间件优缺点及使用场景也都有些心的.所以总结一个关于中间件比较的系列,希望可以对大家有帮助. 1. 什么是中间件 传统的架构模式就是 应用 ...
- 分布式MySQL数据库中间件 mysqlda
1. 概述 1.1. 数据分布式切分方式 分布式架构中最难解决的是数据分布式问题,大部分数据库中间件都以分库分表作为切分方式,好处是通用,但也存在以下问题: 扩容过程需要以切片为单位在库间移动数据.扩 ...
- mysql中ddl和ddm_浅析分布式数据库中间件DDM
前言 DDM是什么?这是华为云Paas推出的分布式数据库中间件,DDM(Distributed Database Middleware)是一个实现了Mysql协议栈的服务器,前端用户可以把它看做一个数 ...
- amoeba mysql下载_amoeba数据库中间件透明实现MYSQL读写分离
Amoeba(变形虫)项目,该开源框架于2008年 开始发布一款 Amoeba for Mysql软件.这个软件致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的 时候充当SQL ...
- mysql kingshard 扩容_kingshard Go语言开发MySQL数据库中间件 - 新手站长网
kingshard是一个由Go开发高性能MySQL Proxy项目,新手站长网分享kingshard的主要功能.帮助文档.github地址.作者信息及kingshard交流群: kingshard简介 ...
- 原创 【ReactJs+springBoot项目——租房】第13章:MySQL主从复制+MyCat数据库中间件+HAProxy+PXC集群
分析目前系统架构中的数据库层存在的问题 分析MySQL数据库的集群方案 学习主从复制(读写分离)架构方案 掌握MyCat数据库中间件的使用 掌握HAProxy复制均衡的使用 掌握PXC集群的使用 多种 ...
- MySQL Proxy实现数据库读写分离
为什么80%的码农都做不了架构师?>>> 可以将master的数据复制分布到多个slave上,然后可以利用slave来分担master的读压力.那么对于前台应用来说,就要考虑如 ...
最新文章
- 为什么Java要把字符串设计成不可变的
- 超级猩猩获 3.6 亿元 D 轮融资,计划今年新开100家门店
- python编码规范手册-PEP8 Python 编码规范整理
- 关于Angular中使用HTML的select和option标签的一些问题
- oracle常用的时间格式转换
- 制打印如下所示的n行数字金字塔_一日一技:在Python中实现阿拉伯数字加上中文数字...
- 数据可视化最容易被人忽略的四大误区,怪不得我的报告总被老板骂
- 爬虫时安装的newspaper 新闻包
- android 横向stepview,一款由Recyclerview打造的步骤控件,支持横向和纵向
- 2020级C语言大作业 - 王国保卫战
- 双向DC/DC变换器设计-硬件主拓扑
- 经济应用文写作【10】
- Iometer存储测试工具参数说明- 2 Access Specifications
- 2022-2027年中国智能化设计行业发展前景及投资战略咨询报告
- Revisiting RCNN: On Awakening the Classification Power of Faster RCNN解读
- html5跳棋游戏,跳棋小游戏大全
- 由于受到新冠疫情的影响,GDP同比增长率从2019年的6.1%下滑到了2.3%
- 51单片机-TLC5615代码
- Chapter3-线性模型线性模型
- 动态域名解析ipv6 群辉dnspod_使用DNSpod动态解析访问黑群晖教程