一句话理解 :MySQL服务端执行完查询后,会一次性把所有结果通过TCP流式推送 给客户端,然后立刻解放资源 (推完就跑);客户端收到后本地慢慢消费 (慢慢吃),服务端完全不管客户端处理快慢。这就是传输解耦。
MySQL JDBC完整传输流程(服务端推完就跑)
1. 服务端执行+预取(独立完成)
SELECT * FROM table LIMIT 1000000;
↓
MySQL Server:
1. 执行查询 → 结果存Server-side Cursor(内存/临时表)
2. 准备Packet流(每包最大net_buffer_length=16MB)
3. **主动推送**所有Packet到客户端TCP连接
关键 :服务端不等客户端反馈,像快递员送完货走人。
2. 客户端接收+本地缓冲(慢慢吃)
客户端JDBC Driver:
1. 接收完整Packet流 → 存本地ResultSet缓冲
2. ResultSet.next() → **本地内存迭代**,不发新请求给服务端!
3. 客户端想多慢就多慢,服务端早已不管
伪代码:
java
// MySQL JDBC内部(简化)
class MySQLResultSet {
byte[] fullResultBuffer; // 本地存完整结果
int currentPos = 0;
boolean next() {
return currentPos < fullResultBuffer.length; // 纯本地!
}
}
3. 服务端资源解放(推完就跑)
服务端视角:
Query开始 → Cursor预取结果 → TCP推Packet流 → 连接空闲 → **服务端线程立即释放**
↓
其他查询可立即使用该线程,服务端不受客户端慢速影响
时序图:
时间轴:
0s MySQL Server: 查询执行+Cursor预取
5s Server: 开始推Packet流 (1GB数据)
35s Server: **推完最后Packet,线程解放** ← 推完就跑!
36s Client: 开始ResultSet.next()本地迭代 ← 慢慢吃
60s Client: 处理完(慢无所谓)
对比Hive JDBC:为什么Hive做不到"推完就跑"
Hive JDBC的"死等"模式
Hive流程:
0s Tez: DAG执行完成,结果存RowSet
5s Client: TFetchResults RPC第1次(拉100KB)
6s Server: 序列化→推 → **线程等待下次RPC**
35s Client: 处理第1批慢 → Server线程**一直空等**
36s Client: TFetchResults第2次 → 重复...
3600s 某批超时 → **Server线程池全堵死**
Hive缺陷:
Server视角:
每次TFetchResultsResp推完 → **必须等客户端下次请求** → 线程被占用到查询结束
百万行=10K RPC → 服务端线程绑定10K秒!
关键技术差异
| 机制 | MySQL JDBC | Hive JDBC |
|---|---|---|
| 传输发起方 | 服务端主动推 | 客户端主动拉 |
| 传输粒度 | 完整结果Packet流(一次性) | 100KB批RPC(反复要) |
| 服务端线程 | 推完立即释放 | 等客户端N次RPC |
| 客户端next() | 本地内存迭代 | 远程RPC调用 |
| 解耦效果 | 服务端5s解放,客户端35s慢慢吃 | 服务端绑定客户端35s+ |
实际影响:缓冲满载时的不同命运
场景:客户端磁盘慢,处理1GB结果需30分钟
MySQL:
5s: 服务端推完Packet流,线程复用给其他查询
30min: 客户端本地慢慢吃ResultSet,服务端完全无感 ✓
Hive:
5s: 服务端推第1批,**等待第2批RPC**
30min: 10K次RPC中某次超时 → 写缓冲满 → **全HiveServer2线程池崩溃** ✗
通俗验证:看日志就懂
MySQL正常日志:
Query OK, 1000000 rows affected (35.12 sec)
Connection idle... ← 服务端已解放
Hive崩溃日志:
TFetchResultsResp sent, waiting next request...
Read timed out after 30s ← 服务端死等30分钟后崩溃
总结:推完就跑的核心价值
MySQL设计哲学 :服务端只负责计算+传输,不负责客户端消费速度。
- 传输层:一次性流式推送
- 消费层:客户端本地责任
Hive设计缺陷 :服务端既负责计算,也要反复响应拉取,变成客户端速度的奴隶。
一句话 :MySQL是'饭菜做好端上桌,你爱慢慢吃服务员不管';Hive是'服务员每次只端一筷子,等你吃完再端下一筷子,你慢了他就饿死等你'。