jdbc底层驱动加载数据机制之防止内存溢出(1)

1.产生背景

默认情况下,jdbc底层驱动加载数据的时候,是加载所有的sql结果集。比如select * from table,这个sql将会一次性加载所有的表中数据到jvm内存中去,如果数据少还没关系,如果数据量大的话,那么势必会出现jvm内存溢出。

同时,这个问题也是我参加面试的时候,面试官问到我的问题,由于之前并没有很深入的研究jdbc底层,一直认为,默认情况下jdbc底层就是通过流去加载(next()一次加载一条到内存,这种想法是错的)

2.jdbc底层怎么控制jvm内存溢出

jdbc通过两个参数来保证 

useCursorFetch--使用游标方式提取

fetchSize--每次提取的大小。也就是一次与数据库服务器通信获取的数据量

这两个参数是关键参数。参数的设置方式

useCursorFetch通过jdbc url参数设置,比如
jdbc:mysql://192.168.5.240:3306/turbo_2?useCursorFetch=true

 

fetchSize通过Statement或PrepareStatement设置,比如:

PreparedStatement pst= conn.prepareStatement(sql);
pst.setFetchSize(5);

有人会问了,是不是每次创建一个statement都要设置一下fetchsize大小,答案是没必要,还有一种简单的方法。

就是通过jdbc url参数附带,跟useCursorFetch一样的方式,如:

jdbc:mysql://192.168.5.240:3306/turbo_2?useCursorFetch=true&defaultFetchSize=4

 

为什么这样可以?参考源码:这个是mysql驱动的源码

在StatementImpl的构造方法中,有如下代码:从连接connection中获取defaultFetchSize的大小,作为初始的fetchsize,如果没有设置,默认的是0

int defaultFetchSize = this.connection.getDefaultFetchSize();

       if (defaultFetchSize != 0) {
                setFetchSize(defaultFetchSize);
            }

 

3.关于jdbc底层参数

jdbc的层级关系如下:

Connection--connection参数,这些参数可以通过jdbc url参数设置 比如:defaultFetchSize maxRows

--Statement或Preparestatment-- statement参数,可以得到以后通过set设置,也可以通过上级connection给出一个默认的,这样所有的statement都将使用默认的参数值。像fetchSize maxRows

 

4.fetchSize与maxRows的区别

fetchSize 是一次与数据库通信获取到的数据量,如果数据量大,会分多次通信获取数据,直到结果集中的数据全部获取完。这个参数主要是用来限制一次获取到的数据量,保证无论结果集有多大,都不会撑爆jvm内存

maxRows 是这个结果集只允许返回的数据量,比如maxRows 设置了2,但是结果集应该有5条,那么无论查询多少次,都只返回2条,后面的3条永远获取不到。这个参数用处不是很大。

 

转载于:https://my.oschina.net/yibuliushen/blog/887509

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值