java mysql 客户端,思考Java版本Mysql客户端的代码

一次偶然的机会debug代码瞅了一眼Mysql客户端的代码(Java版本),最引发我兴趣的是这一句:

20170110203757_874.jpg

execSQL 是一个非常重要的方法,所有SQL语句的最终都是交由这个代码来实现的;这个方法被一个 connectionMutex 锁(这个锁其实就是Connection对象自己,Mysql客户端通过使用了“反射”所以不能直接使用 this )包裹着这就意味着—— 在同一时刻一个Mysql连接只能执行一条SQL语句 。

MySQL客户端的“锁”

带着疑问我走读了这段代码,画一幅图

20170110203759_285.jpg MysqlIO 是负责网络通讯的底层类,使用的是Java是BIO通讯属于“标准”的TCP客户端写法。它内部有三个重要的成员变量

mysqlConnection 是一个Socket类型

mysqlOutput 是一个BufferedOutputStream类型

InputStream 是一个InputStream类型(Mysql做了一点封装理解成BufferedInputStream也没什么问题)

这三个成员变量的初始化是在 MySqlIO 的构造函数完成的,当执行SQL语句的时相当于:

锁住Socket,此时只有当前连接可以使用这个Socket对象(实际的锁范围更大)

mysqlOutput 写入数据包,发送Command(内部称客户端->服务器的请求为Command)

mysqlInput 读取数据包,解析返回结果

如果有多条SQL语句递交给一个 连接 因为Socket被“锁”所以会变成串行执行。

这不是bug,是特性

带着疑问我翻看了Mysql的通讯协议,客户端->服务器的标准格式如下:

20170110203759_406.jpg

3字节表示后面“payload”的长度(所以mysql单数据包最大值是4M);

1字节表示“sequence_id”;这个字段似乎没有什么用途

最后一个是变长的“payload”(长度由第一部分决定)

服务器端->客户端(响应数据包)的标准格式是

20170110203759_59.jpg

1字节表示“类型”

根据不同的类型“payload”会有不同的变化,比如返回的错误信息、受影响的行数等

看到这里我明白原因了。

Mysql的数据包中没有办法区分出一个连接中“不同的数据包”。 A、B两条SQL语句,可以通过一个Socket发送到服务器端;服务器端也会返回两个执行结果。问题是——客户端如何区分出哪个是A的执行结果哪个是B的执行结果呢? 仔细观察上面的数据包唯一的方式是sequence_id,A分配一个id,B分配一个;服务器端在返回的时候把相应的sequence_id带回来表示这是某个SQL语句的执行结果。 遗憾的是——sequence_id根本没用到,服务器端不会返回sequence_id信息。(看Mysql的响应数据包)

正是因为这个原因导致了所有的Mysql客户端 Connection 对象都不是线程安全的。如果想要同时执行多条SQL语句就只能构造多个 Connection 。 有意思的是MongoDB的协议格式几乎和Mysql的一样,messageLength,requestID,opCode;但是响应数据包“修正”了这个bug,messageLength,responseID,opCode。 这就意味着mongodb的conneciton是不需要阻塞的而且根本不需要“线程池”。 (根据我观察 connectionsPerHost 似乎是没有用到,难道这个是为了给大家“安全感”?——我们带线程池,放心用吧)

更多思考

我想到了更多东西,HTTP 2.0的多路复用(Multiplexing)。在HTTP1.0中每个HTTP请求都是一个TCP请求,浏览器载入页面的时候会大量加载css、js、图片、html短时间内会发起大量的TCP请求。在HTTP2.0中同时向一台主机发起css、js、图片可以被承载在同一个TCP连接中。 AMQP中也有相似的设计,叫Channel;一个TCP连接可以被多个线程同时使用。比如用一个TCP连接可以同时实现“订阅”和“发布”消息。 微软RDP协议中也有相同的设计,区分图片、声音、鼠标、键盘操作(Citrix的ICA设计号称的32个通道就是这个意思)。 SSH协议中有一个叫 Channel Mechanism 的东西,它也是为了实现“多路复用”的(这意味着提高了ansible的效率)。

技术就是这么奇妙,很多东西都是你“借鉴我”,我“借鉴你”。相同的问题相同的解决办法,如果 用心其实可以汇编成一本书 ,比如我们上面讲的或许就可以叫——“多路复用的协议设计模式”吧。

欢迎关注公众账号了解更多信息“写程序的康德——思考、批判、理性”

20170110203759_872.jpg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值