分布式 | 中间件是如何处理 Prepare Statement

2022-01-13  本文已影响0人  爱可生开源社区

作者:董诚怡

爱可生 dble 团队开发成员,主要负责 dble 需求开发,故障排查和社区问题解答。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


PS语句(预编译语句)

以下用 缩写 PS 代替 Pepared Statement

PS 的优点

PS 的缺点

分类

使用 dble 侧 PS 必要条件

DBLE 端

客户端

验证是否开启了

PreparedStatement preparedStatement = con.prepareStatement("select t1.id from no_sharding_t1 t1 where t1.id=?");
//可用于验证是否使用了dble 侧 prepare
assert preparedStatement instanceof ServerPreparedStatement;

协议

流程图:

image

可以看到 client <-> dble 通讯使用了 server-side prepare,dble <-> MySQL 通讯使用了 client-side prepare,也就是说后端通讯和普通的即时查询无异,只是需要做一些协议上的包的转换。

原理

  1. prepare 阶段将语句暂存,不进行预编译
  2. execute 阶段拼装参数和语句,将其下发,获得结果后转换为PS协议并返回

游标

游标 的优点

游标 的缺点

分类

后两种是否支持取决于 client 端的 driver,dble 支持的是第一种 server-side cursor。

游标开启必要条件

DBLE 端

注:读写分离场景由于不支持 COM_STMT_FETCH 报文,所以不支持游标。以下描述仅针对分库分表。

客户端

  1. 使用支持游标的driver(MySQL官方的JDBC driver就支持)
  2. 如果是JDBC需开启useServerPrepStmts和useCursorFetch选项
  3. 执行 prepareStatement 后设置 fetchSize,必须大于 0.
  4. 执行 execute

此时是开启游标的,如果对结果集 resultSet进行遍历,会按 fetchSize 的大小一次次地从 dble 取回数据。

验证是否开启了游标

客户端执行第4步后, 调用私有方法 useServerFetch 可验证。

final ResultSet resultSet = preparedStatement.executeQuery();
//可用于验证是否使用了server-side 游标
Method method = com.mysql.cj.jdbc.StatementImpl.class.getDeclaredMethod("useServerFetch");
method.setAccessible(true);
Boolean useServerFetch = (Boolean) method.invoke(preparedStatement);
assert useServerFetch==true;

流程图:

image

原理:

  1. prepare 阶段下发特殊语句。用于计算 SQL 中的列数,这是 client 所需的开启游标的必要条件。
  2. execute 阶段把结果集存储到临时文件
  3. fetch 阶段把结果集分批次一次次取出来

相关参数

maxHeapTableSize

heapTableBufferChunkSize

见文档 https://actiontech.github.io/dble-docs-cn/1.config_file/1.02_bootstrap.cnf.html

上一篇下一篇

猜你喜欢

热点阅读