You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()));
            }
        });
}

补充说明

  1. 为啥try-with-resources管用?
    当try代码块执行完毕后,JVM会自动调用RowSet.close()方法,这个方法会通知MySQL服务器销毁对应的PreparedStatement,彻底释放资源。

  2. 临时应急方案(不推荐长期用)
    如果暂时没法改代码,可以临时调大MySQL的max_prepared_stmt_count配置,执行这条SQL:

    SET GLOBAL max_prepared_stmt_count = 10000;
    

    但这只是治标不治本,调用次数上去了还是会爆错,优先推荐修改代码处理资源释放。

内容的提问来源于stack exchange,提问作者pumbaa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:02:40