执行./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
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29990276/viewspace-2958079/ ,如需转载,请注明出处,否则将追究法律责任。