当前位置: 首页 > 知识库问答 >
问题:

tomcat jdbc连接池中缺少连接

姜明贤
2023-03-14

我们刚刚从dbcp迁移到tomcat jdbc连池。我们在加载中尝试了系统,收到了以下异常:

java.sql.SQLException: [IA1856] Timeout: Pool empty. Unable to fetch a connection in 1 seconds, none available[size:125; busy:90; idle:0; lastwait:1000].
        at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:632)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:174)
        at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:124)
        at com.inneractive.model.mappings.BasicPersistenceEntityMapping.getConnection(BasicPersistenceEntityMapping.java:233)
        at com.inneractive.model.mappings.BasicPersistenceEntityMapping.callWithConnection(BasicPersistenceEntityMapping.java:243)
        at com.inneractive.model.mappings.PersistenceEntityMapping.get(PersistenceEntityMapping.java:194)
        at com.inneractive.model.data.client.ClientUtils.GetClientByExamples(ClientUtils.java:353)
        at com.inneractive.client.ExternalAdRingsClientStart.getClientInfoByRequestParametersOrInsert(ExternalAdRingsClientStart.java:1329)
        at com.inneractive.client.ExternalAdRingsClientStart.newClientSession(ExternalAdRingsClientStart.java:245)
        at com.inneractive.simpleM2M.web.SimpleM2MProtocolBean.generateCampaign(SimpleM2MProtocolBean.java:235)
        at com.inneractive.simpleM2M.web.SimpleM2MProtocolBean.generateCampaign(SimpleM2MProtocolBean.java:219)
        at com.inneractive.simpleM2M.web.AdsServlet.doGet(AdsServlet.java:175)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:555)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:396)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)

请注意:

[size:125; busy:90; idle:0; lastwait:1000]

不忙的连接在哪里?忙的数字在这之后一直在下降,但我们仍然没有得到任何连接。

有什么想法吗?

配置:

<Resource auth="Container" driverClassName="com.mysql.jdbc.Driver"
                factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" loginTimeout="10000"
                maxActive="35" maxIdle="35" maxWait="1000" name="jdbc/mysql"
                password="-----" testOnBorrow="true" testOnReturn="false" type="javax.sql.DataSource"
                url="jdbc:mysql://localhost:3306/my_db?elideSetAutoCommits=true&amp;useDynamicCharsetInfo=false&amp;rewriteBatchedStatements=true&amp;useLocalSessionState=true&amp;useLocalTransactionState=true&amp;alwaysSendSetIsolation=false&amp;cacheServerConfiguration=true&amp;noAccessToProcedureBodies=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"
                username="root" validationQuery="SELECT 1"/>

env:ubuntu和tomcat 6. db-mysql

共有3个答案

越涛
2023-03-14

似乎是池中的一个bug,变量的大小会递增,然后尝试创建连接,但如果创建失败。。。我们的值很大,池中没有实际连接-很糟糕:

    //if we get here, see if we need to create one
    //this is not 100% accurate since it doesn't use a shared
    //atomic variable - a connection can become idle while we are creating
    //a new connection
    if (size.get() < getPoolProperties().getMaxActive()) {
        //atomic duplicate check
        if (size.addAndGet(1) > getPoolProperties().getMaxActive()) {
            //if we got here, two threads passed through the first if
            size.decrementAndGet();
        } else {
            //create a connection, we're below the limit
            return createConnection(now, con, username, password);
        }
    } //end if
申屠秦斩
2023-03-14

“不忙的连接在哪里?”

听起来它们好像已被删除,并且由于某种原因,您的连接池没有尝试重新连接它们。

将此添加到您要连接的URL:

autoReconnect=true

并将this作为属性添加到资源应会导致自动重新连接死连接。

validationQuery="SELECT 1"

此外,这应允许您查看正在断开的连接:

logAbandoned="true"

关于堆栈溢出,有多个类似的问题。

Tomcat连池、空闲连接和连接创建JDBC连接池不会在tomcat中重新打开连接

然而,也可能是你没有完全释放连接,这是导致它们死亡的原因。避免耗尽连接池的JDBC MySql连接池实践

劳和雅
2023-03-14

查看ConnectionPool的源代码。java您似乎在borrowConnection()方法中找到了此代码段:

        //we didn't get a connection, lets see if we timed out
        if (con == null) {
            if ((System.currentTimeMillis() - now) >= maxWait) {
                throw new SQLException("[" + Thread.currentThread().getName()+"] " +
                    "Timeout: Pool empty. Unable to fetch a connection in " + (maxWait / 1000) +
                    " seconds, none available["+busy.size()+" in use].");
            } else {
                //no timeout, lets try again
                continue;
            }
        }

因此,根据这一点,您的连接是空的。

在以下行中检索con的值:

PooledConnection con = idle.poll();

如果跟踪代码,您将看到空闲(取决于您的配置,但默认情况下)为FairBlockingQueue。您可以签出实现以获取提示。

通常,您必须始终关闭ResultSets、语句和连接,并且使用的连接应该正确释放回池中。不正确执行此操作可能会导致连接永远不会关闭=

我建议您对池的状态构建一些详细的日志记录,并对其进行监视以隔离问题。

Apache关于防止数据库连接池泄漏的一些指导原则:

removeAbandoned="true"

放弃的数据库连接将被删除并回收

removeAbandonedTimeout="60"

设置数据库连接在被视为放弃之前处于空闲状态的秒数

logAbandoned="true"

记录放弃数据库连接资源的代码的堆栈跟踪。请记住,“记录放弃的连接会增加每次连接借用的开销,因为必须生成堆栈跟踪。”

我仍然认为稍微增加maxWait值(1200、1500、1700-只是实验,从用户角度来看,响应时间不会有任何差异)将清除那些罕见的情况,在这些情况下,您仍然存在问题。

 类似资料:
  • 我对连接池有一些疑问。在SQL Server连接池文章中提到的内容类似于“打开新连接时,如果连接字符串与现有池不完全匹配,则会创建一个新池。每个进程、每个应用程序域、每个连接字符串以及使用集成安全性时、每个Windows标识将连接池化。” 现在我有了自己的windows窗体应用程序,它具有SQL连接。 > 所以当我打开应用程序时,SQL连接首次打开,并创建了一个池。所以,如果我关闭应用程序池会被自

  • 作为一个专业的服务端开发工程师,我们必须要对连接池、线程池、内存池等有较深理解,并且有自己熟悉的库函数可以让我们轻松驾驭这些不同的 池子。既然他们都叫某某池,那么他们从基础概念上讲,原理和目的几乎是一样的,那就是 复用。 以连接池做引子,我们说说服务端工程师基础必修课。 从我们应用最多的 HTTP 连接、数据库连接、消息推送、日志存储等,所有点到点之间,都需要花样繁多的各色连接。为了传输数据,我们

  • 连接池是客户端内的一个对象,主要是维持现有节点的连接。理论上来讲,节点只有死节点与活节点。 然而在现实世界中,事情绝不会这么明确。有时候节点是处在 “可能挂了但还未确认” 、 “连接超时但未知原因” 或 “最近挂过但现在可用” 的灰色地带中。而连接池的工作就是管理这些无规则的连接,并为客户端提供最稳定的连接状态。 如果一个连接池找不到一个活节点来发送查询,那么就会返回一个 NoNodesAvail

  • Swoole 在 v4 版本后内置了 Library 模块,使用 PHP 代码编写内核功能,使得底层设施更加稳定可靠,并且提供了内置协程连接池,本章节会说明如何使用对应的连接池。 也可以观看Swoole微课程视频教程学习内置连接池的使用。 ConnectionPool ConnectionPool,原始连接池,基于Channel自动调度,支持传入任意构造器(callable),构造器需返回一个连接

  • 安装 composer require hyperf/pool 为什么需要连接池? 当并发量很低的时候,连接可以临时建立,但当服务吞吐达到几百、几千的时候,频繁 建立连接 Connect 和 销毁连接 Close 就有可能会成为服务的一个瓶颈,那么当服务启动的时候,先建立好若干个连接并存放于一个队列中,当需要使用时从队列中取出一个并使用,使用完后再反还到队列去,而对这个队列数据结构进行维护的,就

  • 由于 Swoole 的常驻内存特性,所以 imi 中实现了连接池。所有的数据库、Redis连接,都通过连接池去获取。 定义连接池 连接池的配置,可以写在项目配置文件中,也可以写在服务器配置文件中。 在配置文件中有一个pools节点,里面配置的是连接池。 同步池子仅在task进程使用,异步池子在worker进程使用。一般使用时无需自行判断在哪个进程,框架会自动帮你获取对应的连接。 获取连接 获取池子