java mysql_num_rows_MySQL JDBC FetchSize解析

本文探讨了MySQL JDBC的FetchSize属性,分析了其实现原理,包括cursor-based fetching和streaming模式,并通过源码解释了如何在不同情况下影响数据获取。通过实验支持,确认MySQL JDBC确实支持batch fetch。
摘要由CSDN通过智能技术生成

MySQL JDBC FetchSize解析

根据http://boylook.blog.51cto.com/7934327/1298634提到MySQL JDBC的fetchsize问题.在MySQl官方文档里只提到了streaming模式和fetchALL两种模式,那么是不是就没有中间的状态呢

首先是看Java JDBC的API查看setFetchSize:

setFetchSize(int rows)

Givesthe JDBC driver a hint as to the number of rows that should be fetched from thedatabase when more rows are needed for this ResultSetobject.

查看的结果给出这里的rows只是一个hint,那么对于MySQL JDBC来说是如何实现的呢

查到MySQL一个“bug”http://bugs.mysql.com/bug.phpid=18148里说:

There is experimental support for fetching rows in batches

When using Connector/J 5.0.1 along with more recent builds of the MySQL server, you can add "useCursorFetch=true" to your JDBC url parameters, and the driver will fetch rows in batches of size setFetchSize() as defined in the JDBC API.

One could also argue that the behavior _does_ follow the JDBC API, quoting from the APIDOCS for Statement.setFetchSize():

"Gives the JDBC driver a hint as to the number of rows that should be fetched from the database when more rows are needed. The number of rows specified affects only result sets created using this statement. If the value specified is zero, then the hint is ignored. The default value is zero."

It's only a _hint_. Driver vendors are allowed to ignore hints. The very reason that the wording is there is because there are quite a few vendors who can not adhere to this "contract" in all situations.

useCursorFetch

If connected to MySQL 5.0.2, and setFetchSize() 0 on a statement, should that statement use cursor-based fetching to retrieve rows

false

又说是experiment,又说是hint可能被ignore,到底支持还不不支持呢并且官方文档给出的这个参数没说到底是不是会忽略掉fetchSize.按照故事的尿性来说我该看MySQL JDBC的源码了:

1.首先判断是否可以进行cursor read

if (this.connection.versionMeetsMinimum(5, 0, 2)

this.connection.getUseCursorFetch()

isBinaryEncoded

callingStatement != null

callingStatement.getFetchSize() != 0

callingStatement.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY)

若OK,则RowData rows = new RowDataCursor

2.如果不满足,则判断是否可以进行Streaming Read:

If(this.resultSetType== java.sql.ResultSet.TYPE_FORWARD_ONLY)

(this.resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY) (this.fetchSize == Integer.MIN_VALUE)

如果不满足则rowData = readSingleRowSet

3.否则rowData = new RowDataDynamic

这里主要关注RowDataCursor的next实现方式:next会去调用fetchMoreRows,

3.1 如果fetchsize==Integer.MIN_VALUE,则另fetchsize=1,类似stream 模式

3.2 否则回调fetchRowsViaCursor:

this.sharedSendPacket.writeByte((byte) MysqlDefs.COM_FETCH);

this.sharedSendPacket.writeLong(statementId);

this.sharedSendPacket.writeLong(fetchSize);

sendCommand(MysqlDefs.COM_FETCH, null, this.sharedSendPacket, true,

null);

while ((row = nextRow(columnTypes, columnTypes.length, true,

ResultSet.CONCUR_READ_ONLY, false, useBufferRowExplicit, false, null)) != null) {

fetchedRows.add(row);

}

当执行sendCommand后,看MySQL源码是如何处理的:

317 void Materialized_cursor::fetch(ulong num_rows)

318 {

319 THD *thd= table-in_use;

320

321 int res=0;

322 result-begin_dataset();

323 for(fetch_limit+= num_rows; fetch_count fetch_limit; fetch_count++)

324 {

325 if((res= table-file-rnd_next(table-record[0])))

326 break;

327 /* Send data only if the read was successful. */

328 /*

329 If network write failed (i.e. due to a closed socked),

330 the error has already been set. Just return.

331 */

332 if(result-send_data(item_list))

333 return;

334 }

335

336 switch(res) {

337 case0:

338 thd-server_status|= SERVER_STATUS_CURSOR_EXISTS;

339 result-send_eof();

340 break;

341 case HA_ERR_END_OF_FILE:

342 thd-server_status|= SERVER_STATUS_LAST_ROW_SENT;

343 result-send_eof();

344 close();

345 break;

346 default:

347 table-file-print_error(res,MYF(0));

348 close();

349 break;

350 }

351 }

分析到这里基本上可以确定MySQL也是支持batch fetch的.

MySQL JDBC FetchSize解析 相关文章

MySQL 8 新特性之Clone Plugin(转载)

MySQL 8 新特性之Clone Plugin(转载) https://www.cnblogs.com/vivotech/p/13886206.html#top Clone Plugin是MySQL 8.0.17引入的一个重大特性,为什么要实现这个特性呢个人感觉,主要还是为Group Replication服务。在Group Replication中,添加一个新的节

MySQL学习笔记-3

DML数据操纵语言 1.1 向表中插入数据 关键字 insert ① 写法1 insert into tab_name [(字段1,字段2,...)]values (v1,v2,...)[,(v1,v2,...),... ]; (字段1,字段2,...)必须与(v1,v2,...)在数量,类型上一一对应。 (字段1,字段2,...)可以省略,当然此时后

mysql数据库权限管理

mysql数据库权限管理 # 查看权限# 使用mysql数据库mysql use mysql;# 查看所有用户和权限# 查询主机用户名密码:5.7版本之前的mysql select host,user,plugin,password from user;# 查询主机用户名密码:5.7版本之后的,包括5.7mysql SELECT DISTINCT CONCAT

Canal帮助MySQL进行数据同步

内容来自于《一节课解密阿里巴巴Canal》传统MySQL主从复制原理 Canal原理 Canal整体架构原理检查MySQL配置相关命令这些命令需要在MySQL命令行中去查看执行 #是否启用了日志show variables like 'log_bin';#查看当前日志show master status;#查看MySQL binlog

写给 Poppy 的 MySQL 速查表

昨天 Poppy 问我是不是应该学一些网页开发的东西, 我的回答是这样的: 今天花了点时间汇总了一些 MySQL 简单的命令. ======== 正文分割线 ======== 有哪些常见的数据库: Oracle MySQL SQL Server MongoDB Redis Hadoop 以下所有命令基于数据库 kis_blog 编写,

mysql复习(2):replace

1.replace函数 语法:replace(object,search,replace) tips:object可以是字段名或任意字符串 2. replace into语句 语法:replace into table( col1, col2, col3 ) values ( val1, val2, val3 ) tips:如果使用replace into插入的数据的唯一索引或者主键索引

mysql改为postgresql 语法常见问题

springboot引入postgresql ①pom引入依赖 dependency groupIdorg.postgresql/groupId artifactIdpostgresql/artifactId version9.4.1212/version /dependency ②yml文件 spring: datasource: url: jdbc:postgresql://192.168.10.223:5866/highgo(数据库名称)

MySQL核心知识学习之路(3)

作为一个后端工程师,想必没有人没用过数据库,跟我一起复习一下MySQL吧,本文是我学习《MySQL实战45讲》的总结笔记的第三篇,总结了MySQL的索引相关知识。 上一篇:MySQL核心知识学习之路(2) 1 索引的模型 我们都知道索引的出现是为了提高数据查询的效率

Shiro的Jdbc配置和验证策略(二)

戒色诗: 二八佳人体似酥,腰间仗剑斩凡夫。虽然不见人头落,暗里教君骨髓枯。 一. Shiro 的认证错误 在上一章节的例子中,我们可以看到, Shiro 是通用 Subject 对象的 login() 方法,进行认证判断的。 我们自己在开发中,常常有这么一个需求,在登录时,如

mysql学习05--sum()与count()的查询

name continent area population gdp Afghanistan Asia 652230 25500100 20343000000 Albania Europe 28748 2831741 12960000000 Algeria Africa 2381741 37100000 188681000000 Andorra Europe 468 78115 3712000000 Angola Africa 1246700 20609294 100990

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值