use java mysql connector- // fake mysql select code
- // ... datasource init
- Connection conn = datasource.getConnection();
- PreparedStatement pst = conn.prepareStatement("select id, task_name from t_task where id = ?");
- pst.setLong(1, 31);
- pst.executeQuery();
复制代码 按照直觉, 既然用了 preparedStatement, 执行过一次后会在服务端缓存好预编译的语句, 之后就能省去这个解析过程,直接提交参数执行就好了
- 但是, mysql connector 默认创建的是 ClientPreparedStatement
- public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
- try {
- synchronized(this.getConnectionMutex()) {
- this.checkClosed();
- ClientPreparedStatement pStmt = null;
- boolean canServerPrepare = true;
- String nativeSql = (Boolean)this.processEscapeCodesForPrepStmts.getValue() ? this.nativeSQL(sql) : sql;
- if ((Boolean)this.useServerPrepStmts.getValue() && (Boolean)this.emulateUnsupportedPstmts.getValue()) {
- canServerPrepare = this.canHandleAsServerPreparedStatement(nativeSql);
- }
- // useServerPrepStmts = false
- if ((Boolean)this.useServerPrepStmts.getValue() && canServerPrepare) {
- // ... 省略一些代码
- } else {
- //... 省略一些代码
- pStmt = (ClientPreparedStatement)this.clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
- }
- }
- } else {
- pStmt = (ClientPreparedStatement)this.clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
- }
- return (PreparedStatement)pStmt;
- }
- } catch (CJException var17) {
- throw SQLExceptionsMapping.translateException(var17, this.getExceptionInterceptor());
- }
- }
复制代码 因为默认并没有设置 useServerPrepStmts = true, 默认是false 去指定要求服务端缓存 创建的 clientPrepareStatement 客户端语句
- 是不是 ClientPreparedStatement 看着客户端侧进行一些元数据的缓存?
pst.executeQuery(); 代码中有一段逻辑, 如果cacheResultSetMetadata=true的话,会缓存元数据,但是并没有
- boolean cacheResultSetMetadata = (Boolean)locallyScopedConn.getPropertySet().getBooleanProperty(PropertyKey.cacheResultSetMetadata).getValue();
- String origSql = ((PreparedQuery)this.query).getOriginalSql();
- if (cacheResultSetMetadata) {
- cachedMetadata = locallyScopedConn.getCachedMetaData(origSql);
- }
复制代码 所以,虽然每次还是从服务端拿返回 参数 和 resultSet 的一些元数据
- 最终发往服务端(这边场景是proxy) 的 sql 其实是非参数化的 com_query 命令

- proxy 接收到 com_query 交由 MySQLComQueryPacketExecutor 处理
[code] public Collection |