暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

benchmarksql 压测MySQL报Every derived table must have its own alias解决

原创 姚崇 2023-06-12
777

压测的时候报错

执行./runBenchmark.sh mysql_1000w.properties报错
报错内容如下:

08:58:52,889 [Thread-3] ERROR jTPCCTData : Unexpected SQLException in STOCK_LEVEL 08:58:52,889 [Thread-3] ERROR jTPCCTData : Every derived table must have its own alias java.sql.SQLSyntaxErrorException: Every derived table must have its own alias at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953) at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1009) at jTPCCTData.executeStockLevel(jTPCCTData.java:2110) at jTPCCTData.execute(jTPCCTData.java:205) at jTPCCTerminal.executeTransactions(jTPCCTerminal.java:194) at jTPCCTerminal.run(jTPCCTerminal.java:96) at java.lang.Thread.run(Thread.java:748) 08:58:52,929 [Thread-2] ERROR jTPCCTData : Unexpected SQLException in STOCK_LEVEL 08:58:52,929 [Thread-2] ERROR jTPCCTData : Every derived table must have its own alias java.sql.SQLSyntaxErrorException: Every derived table must have its own alias at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953) at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1009) at jTPCCTData.executeStockLevel(jTPCCTData.java:2110) at jTPCCTData.execute(jTPCCTData.java:205) at jTPCCTerminal.executeTransactions(jTPCCTerminal.java:194) at jTPCCTerminal.run(jTPCCTerminal.java:96) at java.lang.Thread.run(Thread.java:748)

错误分析

可以看到jTPCCTData.executeStockLevel方法报错,查看此方法内容
该错误与SQL查询有关,这里提示的是"Every derived table must have its own alias",也就是说每个派生表必须有自己的别名。这种错误通常在我们在SQL查询中使用子查询或者join操作,但没有给子查询或者join的表提供别名时出现。

private void executeStockLevel(Logger log, jTPCCConnection db) throws Exception { PreparedStatement stmt; ResultSet rs; try { stmt = db.stmtStockLevelSelectLow; stmt.setInt(1, stockLevel.w_id); stmt.setInt(2, stockLevel.threshold); stmt.setInt(3, stockLevel.w_id); stmt.setInt(4, stockLevel.d_id); rs = stmt.executeQuery(); if (!rs.next()) { throw new Exception("Failed to get low-stock for" + " W_ID=" + stockLevel.w_id + " D_ID=" + stockLevel.d_id); } stockLevel.low_stock = rs.getInt("low_stock"); rs.close(); db.commit(); } catch (SQLException se) { log.error("Unexpected SQLException in STOCK_LEVEL"); for (SQLException x = se; x != null; x = x.getNextException()) log.error(x.getMessage()); se.printStackTrace(); try { db.rollback(); } catch (SQLException se2) { throw new Exception("Unexpected SQLException on rollback: " + se2.getMessage()); } } catch (Exception e) { try { db.rollback(); } catch (SQLException se2) { throw new Exception("Unexpected SQLException on rollback: " + se2.getMessage()); } throw e; } }

我们需要找到db.stmtStockLevelSelectLow这个PreparedStatement的定义部分,也就是对应的SQL语句是什么,才能对其进行修改。
找到那个SQL查询语句后,你需要检查这个查询中的每个子查询或者JOIN的表是否都有别名。如果没有,需要为其添加别名。
可以看到PG和Oracle的SQL定义都带了 AS L,将MySQL部分加上即可

default: stmtStockLevelSelectLow = dbConn.prepareStatement( "SELECT count(*) AS low_stock FROM (" + " SELECT s_w_id, s_i_id, s_quantity " + " FROM bmsql_stock " + " WHERE s_w_id = ? AND s_quantity < ? AND s_i_id IN (" + " SELECT ol_i_id " + " FROM bmsql_district " + " JOIN bmsql_order_line ON ol_w_id = d_w_id " + " AND ol_d_id = d_id " + " AND ol_o_id >= d_next_o_id - 20 " + " AND ol_o_id < d_next_o_id " + " WHERE d_w_id = ? AND d_id = ? " + " ) " + " ) AS L"); break; }

重新编译

编译后,可以正常进行压测

11:21:28,205 [main] INFO   jTPCC : Term-00, 
progress: 0.0, tpmTOTAL: 7500.0, tpmC: 0.0
progress: 1.0, tpmTOTAL: 16303.7, tpmC: 7732.3
progress: 2.0, tpmTOTAL: 18422.4, tpmC: 8806.8
progress: 3.0, tpmTOTAL: 18573.8, tpmC: 8957.0
progress: 4.0, tpmTOTAL: 18800.6, tpmC: 8650.7
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论