一、问题描述

QueuePool limit of size 10 overflow 20 reached, connection timed out, timeout 30.00 (Background on this error at: https://sqlalche.me/e/14/3o7r)
在代码运行的过程种抛出这个异常。通过官方文档查找问题解决办法。

二、问题分析

This is possibly the most common runtime error experienced, as it
directly involves the work load of the application surpassing a
configured limit, one which typically applies to nearly all SQLAlchemy
applications.
这可能是最常见的运行时错误,因为它直接涉及超出配置限制的应用程序的工作负载,这通常适用于几乎所有SQLAlchemy应用程序。 The
following points summarize what this error means, beginning with the
most fundamental points that most SQLAlchemy users should already be
familiar with.

下面几点总结了这个错误的含义,能帮助我们理解这个错误本身。

The SQLAlchemy Engine object uses a pool of connections by default

  • SQLAlchemy Engine对象默认情况下使用一个连接池 。这意味着,当使用Engine对象的SQL数据库连接资源,然后释放该资源时,数据库连接本身仍然连接到数据库,并返回到一个内部队列,在这个队列中它可以再次使用。 尽管代码可能会结束与数据库的对话,但在许多情况下,应用程序仍将维护固定数量的数据库连接,直到应用程序结束或池显式释放为止。
  • 因为池,当应用程序使用了一个SQL数据库连接,通常从利用Engine.connect()或使用一个ORM Session进行查询时,这个动作并不一定在获取连接对象的时刻建立到数据库的新连接; 相反,它会向连接池请求一个连接,而连接池通常会从池中检索一个现有的连接以便重用。 如果没有可用的连接,则池将创建一个新的数据库连接,但前提是池的容量没有超过配置的容量。
  • 大多数情况下使用的默认池称为QueuePool。 当你请求这个池给你一个连接,但没有可用的连接时,如果正在使用的连接总数小于配置的值,它将创建一个新的连接。 这个值等于池大小加上最大溢出。 这意味着如果你将引擎配置为:
    engine = create_engine(“mysql://u:p@host/db”, pool_size=10, max_overflow=20)
  • 上述引擎将允许最多30个连接在任何时候,不包括从引擎分离或失效的连接。 如果一个新连接的请求到达,而应用程序的其他部分已经使用了30个连接,则连接池将在超时并引发此错误消息之前阻塞一段固定的时间。
  • 为了允许同时使用更多数量的连接,可以使用create_engine调整池。 pool_size create_engine。 传递给create_engine()函数的Max_overflow参数。 等待连接可用的超时时间可以使用create_engine配置。 pool_timeout参数。
    可以通过设置create_engine将池配置为无限溢出。 Max_overflow设置为“-1”。 在这个设置下,池将仍然保持一个固定的连接池,但是它不会在一个新的连接被请求时阻塞; 如果没有可用的连接,它将无条件地创建一个新连接。
    但是,当以这种方式运行时,如果应用程序出现问题,即它正在使用所有可用的连接资源,那么它最终将达到数据库本身上配置的可用连接的限制,这将再次返回一个错误。 更严重的是,当应用程序耗尽数据库的连接时,它通常会导致大量资源在失败前被耗尽,并且还会干扰依赖于能够连接数据库的其他应用程序和数据库状态机制。
    根据上述情况,可以将连接池看作连接使用的安全阀,它提供了一个关键的保护层,防止恶意应用程序导致整个数据库对所有其他应用程序不可用。 当接收到这个错误消息时,最好修复这个问题,使用过多的连接和/或适当地配置限制,而不是允许无限的溢出,因为这实际上不能解决根本的问题。

三、可能的原因

3.1 应用程序根据池的配置值处理了太多的并发请求 这是最直接的原因。

如果你有一个应用程序运行在一个线程池,允许30并发线程,每个线程使用一个连接,如果你的池没有配置为允许至少30连接检查一次,你会得到这个错误一旦应用程序接收到足够的并发请求。 解决方案是提高池的限制或降低并发线程的数量。

3.2 应用程序没有向池返回连接

这是第二个最常见的原因,即应用程序正在使用连接池,但程序未能释放这些连接,而是让它们保持打开状态。 连接池和ORM Session确实有逻辑,当会话和/或连接对象被垃圾收集时,它会导致底层连接资源被释放,但不能依赖这种行为及时释放资源。
出现这种情况的一个常见原因是,应用程序使用ORM会话,当涉及该会话的工作完成时,不会对它们调用session .close()。 解决方案是确保如果使用ORM ORM会话,如果使用engine 或engine-bound connection对象,明确收于所做的工作,通过适当的.close()方法,或使用一个可用的上下文管理器(“with:”语句)正确地释放资源。
最终发现自己的程序也是这个错误,新建太多连接没有即时释放资源。

3.3 应用程序试图运行长时间运行的事务