使用MySQL Server Side Cursor解决查询数据量过大造成OOM

一、前言

前面介绍了MyBaits中两种使用游标的方式来避免搜查内容过大导致OOM,这两种方式被称为是客户端side的游标,因为mysql client每次从自己的接受buffer获取一条记录,这虽然解决了OOM,但是会造成sqlserver服务器推送记录到client的时候阻塞,那么有没有一种方式可以让mysql server减少阻塞那,答案是肯定的。

二、MySQL Server Side Cursor

2.1 使用

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

  • 必须是select语句
  • 设置了fetchSize>0 在mapper文件里面设置
  • 设置了useCursorFetch=true
  • 数据集类型为ResultSet.TYPE_FORWARD_ONLY
  • 数据集并发设置为ResultSet.CONCUR_READ_ONLY 在数据库链接后面设置:jdbc:mysql://localhost:3306/test?useCursorFetch=true"
  • 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 size
if (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
}

2.2 原理简单介绍

先说下发送原理,client发送select请求给Server后,Server根据条件筛选符合条件的记录,然后就会把记录发送到自己的发送buffer,等buffer满了就flush缓存(这里要注意的是如果client的接受缓存满了,那么Server的发送就会阻塞主,直到client的接受缓存空闲。),通过网络发送到client的接受缓存,当不用游标时候MySqIo就会从接受缓存里面逐个读取记录到resultset。就这样client 从自己的接受缓存读取数据到resultset,同时Server端不断通过网络向client接受缓存发送数据,直到所有记录都放到了resultset。

服务器边的游标则是mysqlclient一次从自己的接受缓存读取fetchSize个记录(如果buffer不够fetchSize也没关系,因为Server一直在向这个buffer 刷新数据)。mysqlclient获取fetchSize个记录放到mysqlclient的游标内部的数组里面,游标获取的时候是从数组里面获取数据,如果数组为空了,在向buffer获取fetchSize个记录。

三、总结对比

服务器边的游标的使用的确可以减少server端阻塞,这是因为client一次从接受缓存读取fetchsize个记录,所以大概率情况下给Server写入腾出了空间。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏七夜安全博客

What!!! so fast

不要以为我是标题党,真的是so fast。。。最近有个小项目的需要,使用golang写了个端口扫描工具,不得不说golang的效率确实比python快的太多了。...

10220
来自专栏张高兴的博客

张高兴的 UWP 开发笔记:应用内启动应用 (UWP Launch UWP)

37190
来自专栏贾鹏辉的技术专栏@CrazyCodeBoy

React Native发布APP之签名打包APK

React Native发布APP之签名打包APK ---- 用React Native开发好APP之后,如何将APP发布以供用户使用呢?一款APP的发布流程...

30450
来自专栏hotqin888的专栏

ONLYOFFICE协作编辑页面中文档下载地址url携带(传输)sessionid测试

onlyoffice协作页面里有个文档下载地址,这个地址是第一个人打开这个文档的时候,服务器会根据这个文档地址,将文档管理服务器里的文档下载到onlyoffic...

21210
来自专栏linux系统运维

原 添加自定义监控项目,配置邮件告警,测

21530
来自专栏琯琯博客

开发 Composer 包详细步骤

一、GitHub 创建一个名 uploadfile 新仓库,并克隆至本地。 二、初始化项目,生成composer.json文件 2.1 步骤 2.2 步骤解释...

806120
来自专栏杂烩

kafka-eagle1.1.9安装 原

源码地址https://github.com/smartloli/kafka-eagle

12410
来自专栏【转载】DRF+Vue+Mysql_生鲜超市系统

四、xadmin后台管理

然后运行脚本 import_category_data.py  数据就可以保存到数据库了

91200
来自专栏互扯程序

Linux常用Shell脚本,值得学习及收藏

在运维中,尤其是linux运维,都知道脚本的重要性,脚本会让我们的 运维事半功倍,所以学会写脚本是我们每个linux运维必须学会的一门功课,这里收藏linux运...

28210
来自专栏FreeBuf

Xdigger Framework:一款网络安全测试辅助框架

*本文作者、Xdigger Framework开发者:guyoung Xdigger Framework是一款基于.Net Framework的网络安全测试辅助...

22370

扫码关注云+社区

领取腾讯云代金券