JDBC--06--报错net_write_timeout---MySQL JDBC StreamResult通信原理
Posted 高高for 循环
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC--06--报错net_write_timeout---MySQL JDBC StreamResult通信原理相关的知识,希望对你有一定的参考价值。
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
1.报错背景
2.原因分析
mysql JDBC StreamResult通信原理
- JDBC与数据库之间的通信是通过Socket完成的,因此我们可以把数据库当成一个SocketServer的提供方,因此当SocketServer返回数据的时候(类似于SQL结果集的返回)其流程是:服务端程序数据(数据库) -> 内核Socket Buffer -> 网络 -> 客户端Socket Buffer -> 客户端程序(JDBC所在的JVM内存)
- 到目前为止,IT行业中大家所看到的JDBC无论是:MySQL JDBC、SQL Server JDBC、PG JDBC、Oracle JDBC。甚至于是NoSQL的Client:Redis Client、MongoDB Client,甚至于是SSH通信目前在Java中的实现做法也基本都是如此,也就是都是基于TCP通信的机制,它们的大致原理如下图所示:
方式1:直接使用MySQL JDBC默认参数读取数据,为什么会挂?
方式2:JDBC参数上设置useCursorFetch=true可以解决问题
- 这个方案配合FetchSize设置,确实可以解决问题,这个方案其实就是告诉MySQL服务端我要多少数据,每次要多少数据,通信过程有点像这样:
在这里的计算中,还没有包含系统调用次数增加了很多,线程等待和唤醒的上下文次数变多,网络包重传的情况对整体性能的影响,因此这种方案看似合理,但是性能确不怎么样。
另外,由于MySQL方不知道客户端什么时候将数据消费完,而自身的对应表可能会有DML写入操作,此时MySQL需要建立一个临时空间来存放需要拿走的数据。因此对于当你启用useCursorFetch读取大表的时候会看到MySQL上的几个现象:
- IOPS飙升,因为存在大量的IO读取和写入,这个动作是正在准备要返回的数据到临时空间中,此时监控MySQL的网络输出是没有变化的。由于IO写入很大,如果是普通硬盘,此时可能会引起业务写入的抖动
- 磁盘空间飙升,这块临时空间可能比原表更大,如果这个表在整个库内部占用相当大的比重有可能会导致数据库磁盘写满,空间会在结果集读取完成后或者客户端发起Result.close()时由MySQL去回收。
- CPU和内存会有一定比例的上升,根据CPU的能力决定。
- 客户端JDBC发起SQL后,长时间等待SQL响应数据,这段时间就是服务端在准备数据,这个等待与原始的JDBC不设置任何参数的方式也表现出等待,在内部原理上是不一样的,前者是一直在读取网络缓冲区的数据,没有响应给业务,现在是MySQL数据库在准备临时数据空间,没有响应给JDBC。
- 在数据准备完成后,开始传输数据的阶段,网络响应开始飙升,IOPS由“读写”转变为“读取”。
方式3:Stream读取数据
3.解决方案
- 由于当前session参数的优先级大于数据库的全局参数优先级,直接修改数据的net_write_timeout是不能解决问题的
- 需要在jdbc的连接参数中给netTimeoutForStreamingResults指定新的值,具体指的大小序言应用根据使用场景评估(单挑数据处理耗时),目前根据经验推介设置3600
以上是关于JDBC--06--报错net_write_timeout---MySQL JDBC StreamResult通信原理的主要内容,如果未能解决你的问题,请参考以下文章