Vert.x 3.9.8下MySQL预查询未关闭导致多次调用updateToDb方法触发Can't create more than max_prepared_stmt_count错误
问题分析与解决方案
问题根源
咱们先唠清楚为啥会触发Can't create more than max_prepared_stmt_count这个报错:
- Vert.x的
MySQLPool.preparedQuery()会在MySQL服务器端创建一个PreparedStatement对象; - 你现在的代码只获取了查询结果
RowSet,但完全没处理资源释放——MySQL服务器会一直攥着这个PreparedStatement不放手; - 反复调用
updateToDb后,服务器上堆积的PreparedStatement数量就会超过MySQL配置的max_prepared_stmt_count上限,直接炸出错误。
解决办法
Vert.x 3.9.x版本里,RowSet类刚好实现了AutoCloseable接口,咱们可以用Java的try-with-resources语法自动关闭资源,确保每次查询后都让MySQL服务器销毁对应的PreparedStatement。
修改后的代码如下:
public static void updateToDb(MySQLPool jdbcClient, String sql, JsonArray params, Handler<AsyncResult<Object>> handler) { jdbcClient .preparedQuery(sql) .execute(Tuple.tuple(params.getList()), ar -> { if (ar.succeeded()) { // 用try-with-resources自动关闭RowSet,释放服务器端的PreparedStatement try (RowSet<Row> rows = ar.result()) { handler.handle(Future.succeededFuture(rows.rowCount())); } catch (Exception e) { handler.handle(Future.failedFuture(e.getMessage())); } } else { handler.handle(Future.failedFuture(ar.cause().getMessage())); } }); }
补充说明
为啥try-with-resources管用?
当try代码块执行完毕后,JVM会自动调用RowSet.close()方法,这个方法会通知MySQL服务器销毁对应的PreparedStatement,彻底释放资源。临时应急方案(不推荐长期用)
如果暂时没法改代码,可以临时调大MySQL的max_prepared_stmt_count配置,执行这条SQL:SET GLOBAL max_prepared_stmt_count = 10000;但这只是治标不治本,调用次数上去了还是会爆错,优先推荐修改代码处理资源释放。
内容的提问来源于stack exchange,提问作者pumbaa
相关产品推荐
相关产品推荐

