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

Vertx应用中简单数据库更新操作耗时3分钟的排查求助

Vertx 中简单数据库更新操作耗时3分钟的排查分析

我在Java Vertx应用里执行一个非常简单的数据库更新操作,但耗时居然长达3分钟。下面是控制台输出和相关代码,求帮忙排查原因。

控制台输出

2022-07-19 11:54:32.039+0430 [vert.x-eventloop-thread-1] DEBUG com.job.PrintJobHandler -  onSuccess for startPrintJob()   Job Completed Successfully!!!!
2022-07-19 11:54:32.039+0430 [vert.x-eventloop-thread-1] DEBUG com.dao.JobDao - Inside setJobFinishedDate() 14
2022-07-19 11:54:32.039+0430 [vert.x-eventloop-thread-1] DEBUG com.dao.JobDao - Tuple for Parent UID values: [2022-07-19 11:54:32,14]
2022-07-19 11:57:45.733+0430 [vert.x-eventloop-thread-1] DEBUG com.dao.JobDao - Updated job table's finished_on column!!!!!!!!!!!!!!!!!!!!!!!!! 
2022-07-19 11:57:45.733+0430 [vert.x-eventloop-thread-1] DEBUG com.job.PrintJobHandler - Job Completed Successfully!!!!
2022-07-19 11:57:45.734+0430 [vert.x-eventloop-thread-1] DEBUG com.job.PrintJobHandler -  onSuccess for startPrintJob()   Server sent msg --- Finished printing Job ID::::: 14

相关代码

调用更新方法的代码

startPrintJob(jobID, context)
            .onFailure(error -> {
                LOG.debug("startTest() Failed: ", error);
            })
            .onSuccess(res -> { 
                LOG.debug(" onSuccess for startPrintJob()   " + res);
                jobDao.setJobFinishedDate(jobID)
                .onSuccess(result -> {
                    LOG.debug(res);
                    String updatedStatus = "Server sent msg --- Finished printing Job ID::::: "+jobID;
                    
                    context.response()
                    .setStatusCode(200)
                    .putHeader("content-type", "application/json; charset=utf-8")
                    .end(Json.encodePrettily(updatedStatus));
                    
                    LOG.debug(" onSuccess for startPrintJob()   " + updatedStatus);
                });             
            });

更新方法实现

public Future<String> setJobFinishedDate(int jobID) {
        
        Promise<String> promise = Promise.promise();
        
        LOG.debug("Inside setJobFinishedDate() "+jobID);
        LocalDateTime issuedAt = LocalDateTime.now();
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");      
        Tuple batch = Tuple.of(issuedAt.format(format), jobID);
        LOG.debug("Tuple for Parent UID values: " + batch.deepToString());

        // Execute the query
        db.preparedQuery("UPDATE job SET finished_on=? WHERE id=?;").execute(batch, res -> {
            if (res.succeeded()) {
                LOG.debug("Updated job table's finished_on column!!!!!!!!!!!!!!!!!!!!!!!!! ");
                promise.complete("Updated job table's finished_on column!!");
            } else {
                System.out.println("Batch failed for UPDATE job table's finished_on column!!" + res.cause());
            }
        });
        return promise.future();
    }

可能的排查方向

  • 数据库锁等待:目标行(id=14的job记录)可能被其他事务持有锁未释放,导致UPDATE语句等待。可以通过数据库工具查看锁状态(比如MySQL用SHOW ENGINE INNODB STATUS,PostgreSQL用SELECT * FROM pg_locks)。
  • 连接池资源耗尽:检查Vertx数据库连接池的配置(最大连接数、等待超时等),确认是否有请求在等待空闲连接。
  • 索引缺失:确认job表的id字段是否为主键或有索引,无索引会导致全表扫描,拖慢更新速度。
  • 时间类型不匹配:代码中将LocalDateTime转为字符串传入,若finished_on是数据库的datetime/timestamp类型,直接传入LocalDateTime对象可避免类型转换的隐性问题。
  • 数据库性能瓶颈:查看数据库的CPU、磁盘IO负载,开启慢查询日志,确认这条UPDATE是否被标记为慢查询。
  • 事件线程阻塞:虽然日志显示操作在eventloop线程,但需确认数据库驱动是否真的异步执行,避免其他阻塞操作占用事件线程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:03:21