使用MySQL Server Side Cursor解决查询数据量过大造成OOM和网络IO频繁的问题

一、前言

前面介绍了MyBaits中两种使用游标的方式来避免搜查内容过大导致JVM OOM,这两种方式被称为是客户端side的游标,因为mysql client每次从mysqlserver获取一条记录,这虽然解决了OOM,但是会造成IO网络比较频繁,那么有没有一种方式可以让mysql server一次返回fetchsize个记录那?答案是肯定的。

二、MySQL Server Side Cursor

2.1 使用

要使用MySQL Server Side游标需要满足下面条件:

  • 必须是select语句

  • 设置了fetchSize>0

  • 设置了useCursorFetch=true

  • 数据集类型为ResultSet.TYPE_FORWARD_ONLY

  • 数据集并发设置为ResultSet.CONCUR_READ_ONLY

  • Server versions 5.0.5 or newer

这是因为代码层面做了下面判断:

// we only create cursor-backed result sets if// a) The query is a SELECT// b) The server supports it// c) We know it is forward-only (note this doesn't preclude updatable result sets)// d) The user has set a fetch sizeif (this.resultFields != null && this.useCursorFetch && getResultSetType() == ResultSet.TYPE_FORWARD_ONLY
        && getResultSetConcurrency() == ResultSet.CONCUR_READ_ONLY && getFetchSize() > 0) {
    packet.writeByte(OPEN_CURSOR_FLAG);    //                  usingCursor = true;} else {
    packet.writeByte((byte) 0); // placeholder for flags} Server versions 5.0.5 or newer will only open a cursor and set this flag if they can, otherwise they punt and go back to mysql_store_results()// behavior//if (this.connection.versionMeetsMinimum(5, 0, 5)) {
    usingCursor = (this.serverStatus & SERVER_STATUS_CURSOR_EXISTS) != 0;
}

2.2 原理简单介绍

服务器边的游标是mysqlclient先从mysqlserver获取fetchSize个记录放到mysqlclient的游标内部的数组里面,游标获取的时候是从数组里面获取数据,如果数组为空了,在向mysql server获取fetchSize个记录。

三、总结对比

服务器边的游标的使用的确可以减少网络IO,但是这是使用占用MySQL服务器资源来实现的,因为服务器这边肯定要做维护每次返回fetchSize的事情,所以并不见的使用服务器端游标比客户端的就好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值