首先说明一下,本文不是介绍大名鼎鼎的那个mysql proxy,我做的这个应该是mysql客户端的代理。
首先说明一下背景,公司有一台数据库服务器,但是由于安全的需要,只对几个ip作了授权,其他的机器不能连接上。
如下图所示:
现在有个工具开发需求,需要从每个人的工作pc上访问DB Server,由于不能直连,就在授权pc上做了一个mysql的代理。代理是一个小型的server,采用多进程的模式,用于接收工作pc上客户端的连接,并执行客户端的请求,然后发送结果给客户端。其实这和mysqlclient功能很像。
首先定义和网络交互的包
请求包:
typedef struct __RequestMsg
{
int type;
int dataLen;
char data[1];
}RequestMsg;
其中type表示请求执行的类型,一般来说,数据库访问可以分为两个类型,一种是需要返回结果集的,如select,一种是不需要返回结果集,只需要指明操作是否成功的,如insert,delete,update等。type就是指明这种请求的类型。
dataLen用于指明data数据的长度。data数据中存储的内容,根据type不同有不同的含义。
响应包:
typedef struct __Row
{
int fieldNum;
char data[1];
}Row;
typedef struct __ResponseMsg
{
int bSuccess;
int errCode;
int rowNum;
int dataLen;
char data[1];
}ResponseMsg;
相应包主要是为了返回select的内容而设计的。其中fieldNum指明了结果集中field的个数,bSuccess表示操作是否成功,errCode表示如果出错的错误码。rowNum表示结果集中的行数,dataLen表示结果集的缓冲区长度,data存放具体的结果数据。当然,如果执行的是insert等不需要返回结果的操作,data为空。
同事提供两个api:
typedef map<string,string> mapString;
int getAll(ResponseMsg* res,vector<mapString>& vecMapStr);
int fmtMsg(vector<string> fieldList,vector<vecString> valueList,char** resBuff,int& resLen);
fmtMsg的作用是格式话结果到一个内存缓冲区中,此缓冲区用于网络发送数据。用户服务端。
getAll用于从缓冲区中读出结果数据。用于客户端。
这样就完成了客户端和服务端的通信。
同样,服务端可以管理多个mysql数据库,做得再复杂一点还可以做负载均衡、读写分离之类的事情,当然,网络上现在有很多这样的工具
本来是一个很简单的小工具,但是我想也许有人用得着,源代码还没有整理,有点乱,等整理完了上传上来