当前位置: 首页 > news >正文

慕课网网站开发背景建设局是做什么的

慕课网网站开发背景,建设局是做什么的,wordpress怎么使用固定连接,网站 动态内容加速MySQL 驱动 Add Batch 优化实现 MySQL 驱动会在 JDBC URL 添加 rewriteBatchedStatements 参数时#xff0c;对 batch 操作进行优化。本文测试各种参数组合的行为#xff0c;并结合驱动代码简单分析。 batch参数组合行为 useServerPrepStmts 参数 PreparedStatement psmt…MySQL 驱动 Add Batch 优化实现 MySQL 驱动会在 JDBC URL 添加 rewriteBatchedStatements 参数时对 batch 操作进行优化。本文测试各种参数组合的行为并结合驱动代码简单分析。 batch参数组合行为 useServerPrepStmts 参数 PreparedStatement psmt connection.prepareStatement(DELETE FROM t_order WHERE order_id ?); psmt.setObject(1, 1); psmt.execute();开启: 使用服务端预编译先发送 prepared 语句再发送 excute 语句 不开启: mysql 驱动会将占位符填充后明文下发sql. 比如 DELETE FROM t_order WHERE order_id ?; 语句 MySQL 驱动会下发 DELETE FROM t_order WHERE order_id 1; allowMultiQueries 参数 Statement statement connection.createStatement(); statement.execute(DELETE FROM t_order WHERE order_id 1;DELETE FROM t_order WHERE order_id 2;);不开启: 服务端不支持 DELETE FROM t_order WHERE order_id 1;DELETE FROM t_order WHERE order_id 2; 这样的批量delete语句 开启: 支持多语句比如 DELETE FROM t_order WHERE order_id 1;DELETE FROM t_order WHERE order_id 2; rewriteBatchedStatements 参数 PreparedStatement psmt connection.prepareStatement(DELETE FROM t_order WHERE order_id ?); for (int i 1; i 500; i) {psmt.setObject(1, i);psmt.addBatch(); } psmt.executeBatch();不开启: batch 操作在 addBatch 时一条条下发参数值。 开启: 在执行 executeBatch 时,将 batch 操作改写后批量下发改写后的 SQL 比如 DELETE FROM t_order WHERE order_id 1;DELETE FROM t_order WHERE order_id 2;…;DELETE FROM t_order WHERE order_id 500; useServerPrepStmtsallowMultiQueries 参数 PreparedStatement psmt connection.prepareStatement(DELETE FROM t_order WHERE order_id ?;DELETE FROM t_order WHERE order_id ?;); psmt.execute();虽然开启了服务端预编译参数 useServerPrepStmts但是 MySQL JDBC 驱动会判断预编译 SQL 不支持 allowMultiQueries会直接转换成客户端预编译也就时会将占位符赋值后下发到 mysql。 比如对于以下 SQL: DELETE FROM t_order WHERE order_id ?;DELETE FROM t_order WHERE order_id ?; 客户端会将占位符填充后发送: DELETE FROM t_order WHERE order_id 1;DELETE FROM t_order WHERE order_id 2; useServerPrepStmtsrewriteBatchedStatements 参数 PreparedStatement psmt connection.prepareStatement(DELETE FROM t_order WHERE order_id ?); for (int i 1; i 500; i) {psmt.setObject(1, i);psmt.addBatch(); } psmt.executeBatch();对于 DELETE FROM t_order WHERE order_id ? 的 batch 语句 会转换成 DELETE FROM t_order WHERE order_id ?;DELETE FROM t_order WHERE order_id ?;多语句下发但是服务端返回不支持。 然后客户端再使用客户端预编译尝试发送(会先发送 set multi option on 包,执行完再关闭该标识)然后下发多语句 DELETE FROM t_order WHERE order_id 1;DELETE FROM t_order WHERE order_id 2;…;DELETE FROM t_order WHERE order_id 500; useServerPrepStmtsallowMultiQueriesrewriteBatchedStatements 参数 PreparedStatement psmt connection.prepareStatement(DELETE FROM t_order WHERE order_id ?); for (int i 1; i 500; i) {psmt.setObject(1, i);psmt.addBatch(); } psmt.executeBatch();当执行 batch delete 语句时 虽然开启了 useServerPrepStmts 预编译参数但是 MySQL JDBC 驱动会判断预编译 SQL 不支持 allowMultiQueries会直接转换成客户端预编译也就将占位符赋值后下发到服务端。 也就是发送 DELETE FROM t_order WHERE order_id 1;DELETE FROM t_order WHERE order_id 2;…;DELETE FROM t_order WHERE order_id 500; MySQL 驱动代码分析 下面结合驱动代码简单分析两组参数的流程: 1.useServerPrepStmtsrewriteBatchedStatementsallowMultiQueries 参数 // 测试 demo // jdbc:mysql://localhost:3306/test?serverTimezoneUTCuseSSLfalseallowPublicKeyRetrievaltrueuseServerPrepStmtstruecachePrepStmtstrueprepStmtCacheSize512prepStmtCacheSqlLimit8000rewriteBatchedStatementstrueallowMultiQueriestrue PreparedStatement psmt connection.prepareStatement(DELETE FROM t_order WHERE order_id ?); for (int i 1; i 500; i) {psmt.setObject(1, i);psmt.addBatch(); } psmt.executeBatch();MySQL驱动处理逻辑 1.prepareStatement 当执行 prepareStatement() 时因为开启了 useServerPrepStmts 参数所以会下发预编译 sql 给 server 端。 PreparedStatement psmt connection.prepareStatement(sql);相关调用栈如下 com.mysql.cj.jdbc.ConnectionImpl#prepareStatementcom.mysql.cj.jdbc.ConnectionImpl#canHandleAsServerPreparedStatement1.判断当前sql是否支持服务端预编译com.mysql.cj.jdbc.ServerPreparedStatement#getInstancecom.mysql.cj.jdbc.ServerPreparedStatement#serverPrepare2.下发预编译sqlcom.mysql.cj.ServerPreparedQuery#serverPreparecom.mysql.cj.protocol.a.NativeMessageBuilder#buildComStmtPreparecom.mysql.cj.NativeSession#sendCommand发包com.mysql.cj.protocol.a.NativeProtocol#readcom.mysql.cj.protocol.a.ColumnDefinitionReader#unpackField1.开启 useServerPrepStmts 参数(emulateUnsupportedPstmts 参数默认就为true)会再根据 canHandleAsServerPreparedStatement() 判断当前 sql 是否支持服务端预编译。 2.canHandleAsServerPreparedStatement()方法会通过 StringUtils._canHandleAsServerPreparedStatementNoCache() 方法检测 sql 是否可以支持服务端预编译。 com.mysql.cj.jdbc.ServerPreparedStatement#getInstance 发送预编译 sql 2.addBatch 添加参数即可不和服务端交互。 3.executeBatch 调用栈: com.mysql.cj.jdbc.StatementImpl#executeBatchcom.mysql.cj.jdbc.ClientPreparedStatement#executeBatchInternalcom.mysql.cj.jdbc.StatementImpl#statementBeginscom.mysql.cj.ServerPreparedQuery#statementBeginscom.mysql.cj.AbstractQuery#statementBeginscom.mysql.cj.AbstractPreparedQuery#getParseInfocom.mysql.cj.ParseInfo#canRewriteAsMultiValueInsertAtSqlLevel 是否支持insert values改写优化com.mysql.cj.jdbc.ClientPreparedStatement#executePreparedBatchAsMultiStatement 多语句执行优化com.mysql.cj.AbstractQuery#getBatchedArgscom.mysql.cj.AbstractPreparedQuery#computeBatchSize 计算批次大小com.mysql.cj.ServerPreparedQuery#computeMaxParameterSetSizeAndBatchSizecom.mysql.cj.jdbc.ClientPreparedStatement#generateMultiStatementForBatchcom.mysql.cj.jdbc.ConnectionImpl#prepareStatementcom.mysql.cj.jdbc.ConnectionImpl#prepareStatementcom.mysql.cj.jdbc.ServerPreparedStatement#setOneBatchedParameterSetcom.mysql.cj.jdbc.ClientPreparedStatement#executecom.mysql.cj.jdbc.ClientPreparedStatement#checkReadOnlySafeStatementcom.mysql.cj.protocol.a.NativeMessageBuilder#buildComQuerycom.mysql.cj.NativeSession#sendCommand由于开启了 rewriteBatchedStatements 参数并且 delelte batch size 大于 3,会通过 executePreparedBatchAsMultiStatement 优化成 批量 delete. // 开启 rewriteBatchedStatements 参数 if (!this.batchHasPlainStatements this.rewriteBatchedStatements.getValue()) {// batch size 3,则将 sql 转成 multi deleteif (!this.batchHasPlainStatements this.query.getBatchedArgs() ! null this.query.getBatchedArgs().size() 3 /* cost of option setting rt-wise */) {return executePreparedBatchAsMultiStatement(batchTimeout);} }executePreparedBatchAsMultiStatement 方法 计算需要分几个批次下发。正常500条sql一个批次即可。 // 根据上面得到的batch sql的长度确定分几个批次下发 multi sql; /*** Computes the optimum number of batched parameter lists to send* without overflowing max_allowed_packet.* * param numBatchedArgs* original batch size* return computed batch size*/ public int computeBatchSize(int numBatchedArgs) {long[] combinedValues computeMaxParameterSetSizeAndBatchSize(numBatchedArgs);long maxSizeOfParameterSet combinedValues[0];long sizeOfEntireBatch combinedValues[1];// 整个 batch sql 的长度不能超长正常走到这个分支里if (sizeOfEntireBatch this.maxAllowedPacket.getValue() - this.originalSql.length()) {return numBatchedArgs;}return (int) Math.max(1, (this.maxAllowedPacket.getValue() - this.originalSql.length()) / maxSizeOfParameterSet); }计算方法如下 // 计算 maxSizeOfParameterSet: 每个参数中最大的长度 // sizeOfEntireBatch: batch所有参数长度相加 /*** Computes the maximum parameter set size and the size of the entire batch given* the number of arguments in the batch.*/ Override protected long[] computeMaxParameterSetSizeAndBatchSize(int numBatchedArgs) {long sizeOfEntireBatch 1 /* com_execute */4 /* stmt id */ 1 /* flags */ 4 /* batch count padding */;long maxSizeOfParameterSet 0;for (int i 0; i numBatchedArgs; i) {ServerPreparedQueryBindValue[] paramArg ((ServerPreparedQueryBindings) this.batchedArgs.get(i)).getBindValues();long sizeOfParameterSet (this.parameterCount 7) / 8; // for isNullsizeOfParameterSet this.parameterCount * 2; // have to send typesServerPreparedQueryBindValue[] parameterBindings this.queryBindings.getBindValues();for (int j 0; j parameterBindings.length; j) {if (!paramArg[j].isNull()) {long size paramArg[j].getBoundLength();if (paramArg[j].isStream()) {if (size ! -1) {sizeOfParameterSet size;}} else {sizeOfParameterSet size;}}}sizeOfEntireBatch sizeOfParameterSet;if (sizeOfParameterSet maxSizeOfParameterSet) {maxSizeOfParameterSet sizeOfParameterSet;}}return new long[] { maxSizeOfParameterSet, sizeOfEntireBatch }; }拼接预编译sql,此时还有?号占位符 ((Wrapper) locallyScopedConn.prepareStatement(generateMultiStatementForBatch(numValuesPerBatch))).unwrap(java.sql.PreparedStatement.class);得到sql如下 DELETE FROM t_order WHERE order_id ?;DELETE FROM t_order WHERE order_id ?;......执行 prepareStatement将上面的批量delete语句执行预编译。 这里逻辑和第一步里的 prepareStatement 类似也需要判断当前批量delete sql是否支持服务端预编译。 这里可以看到开启 allowMultiQueries 参数之后驱动会查找 sql 里是否包含 ; 号如果包含不支持服务端预编译。后面会走客户端预编译流程。 客户端预编译执行批量delete 设置参数 // 给?号占位符塞值 batchedParamIndex setOneBatchedParameterSet(batchedStatement, batchedParamIndex, this.query.getBatchedArgs().get(batchCounter));执行批量delete语句 2.useServerPrepStmtsrewriteBatchedStatements 参数 1.下发预编译sql 2.设置 multi statement on 3.多语句预编译sql,执行返回失败 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near DELETE FROM t_order WHERE order_id ?;DELETE FROM t_order WHERE order_id ’ at line 1 代码就是服务端prepared返回失败会再用 client Prepare statement 重试 4.client Prepare statement 重新批量delete 语句
http://www.laogonggong.com/news/126016.html

相关文章:

  • thinkphp 网站根目录地址自己做网站需要什么程序
  • 省内注销二建 建设部网站更新慢微信小程序怎么制作游戏
  • 移动端网站设计欣赏消费金融网站建设
  • 超实用网站如何修改wordpress的语言
  • 外文网站开发制作好的网站必须申请
  • 怎么参考已有网站做新站黄陂区建设局网站
  • 中英文微信网站开发城市建设管理网站
  • 哈尔滨搭建网站深圳市设计网站公司
  • 网站制作后台怎么做wap注册
  • 为什么做网站特效用用插件wordpress 苏醒
  • wordpress加速网站插件网站推广计划包括哪些
  • 新乡营销型网站机械免费网站制作
  • 网站建设 镇江万达手机网站建设代理商
  • vps 同时翻墙和做网站哪些建材网站可以做宣传
  • 个人兼职网站建设网站建设哈尔滨app开发2
  • 文山网站建设代理钦州房产网站建设
  • 旅游景点企业网站排名免费下载模板的网站有哪些
  • 苏州城乡建设局网站质检员app应用网站html5模板
  • 衡阳市建设局网站org后缀做网站行
  • 网站建设公司考察重庆电子工程职业学院招生信息网
  • 佛山网站制作哪家便宜青浦建设网站公司
  • 鄂州网站制作企业专业的论坛网站建设开发
  • 泸州百度做网站联系开发者模式是干什么的
  • 西安网站建设 北郊wordpress如何使用插件
  • 青岛seo网站推广建一个网站需要做什么的
  • 杭州网站设计制作网站建设需要注意的事情
  • 浏览器怎么打开网站服务器下载大庆网站建设大庆
  • 学习之家网站小程序开发外包
  • 竞价网站做招商加盟可以不备案吗网站建设鄂尔多斯
  • 保定建设网站公司wordpress怎么登录