连接池


连接池是一种标准技术,用于在内存中维护长时间运行的连接以实现高效重用,以及为应用程序可能同时使用的连接总数提供管理。


特别是对于服务器端 Web 应用程序,连接池是在内存中维护活动数据库连接“池”的标准方法,这些连接在请求之间重复使用。


SQLAlchemy 包括几个与 Engine 集成的连接池实现。它们还可以直接用于希望将池添加到其他普通 DBAPI 方法中的应用程序。


连接池配置


create_engine() 函数在大多数情况下都有一个 QueuePool 集成,预配置了合理的池默认值。 如果 您阅读本节只是为了了解如何启用池化 - 恭喜! 您已经完成了。


最常见的 QueuePool 调优参数可以作为关键字参数直接传递给 create_engine(): pool_sizemax_overflowpool_recyclepool_timeout。例如:

engine = create_engine(
    "postgresql+psycopg2://me@localhost/mydb", pool_size=20, max_overflow=0
)


所有 SQLAlchemy 池实现都有一个共同点,即它们都没有“预先创建”连接 - 所有实现都等到第一次使用后再创建连接。此时,如果没有针对更多连接发出额外的并发签出请求,则不会创建其他连接。这就是为什么 create_engine() 默认使用 QueuePool 是完全可以的 大小为 5,而不考虑应用程序是否真的需要 5 个连接 queued up - 如果应用程序 实际上同时使用了 5 个连接,在这种情况下,使用 small pool 是完全合适的默认行为。


注意


QueuePool与 asyncio 不兼容。使用 create_async_engine 创建 而是使用 AsyncEngine,即 AsyncAdaptedQueuePool 类,该类使用与 asyncio 兼容的队列实现。


切换 Pool 实现


使用 create_engine() 的不同类型的池的常用方法 是使用 poolClass 参数。此参数接受从 sqlalchemy.pool 模块导入的类,并为您处理构建池的详细信息。这里的一个常见用例是当要禁用连接池时,这可以通过使用 NullPool 实现来实现:

from sqlalchemy.pool import NullPool

engine = create_engine(
    "postgresql+psycopg2://scott:tiger@localhost/test", poolclass=NullPool
)


使用自定义连接函数


有关各种连接自定义例程的概要,请参阅自定义 DBAPI connect() 参数/连接例程部分


构造矿池


要单独使用 Pool,creator 函数是唯一需要的参数,首先传递,然后是任何其他选项:

import sqlalchemy.pool as pool
import psycopg2


def getconn():
    c = psycopg2.connect(user="ed", host="127.0.0.1", dbname="test")
    return c


mypool = pool.QueuePool(getconn, max_overflow=10, pool_size=5)


然后,可以使用 Pool.connect() 函数。此方法的返回值是包含在透明代理中的 DBAPI 连接:

# get a connection
conn = mypool.connect()

# use it
cursor_obj = conn.cursor()
cursor_obj.execute("select foo")


透明代理的目的是拦截 close() 调用,这样就不会关闭 DBAPI 连接,而是将其返回到池中:

# "close" the connection.  Returns
# it to the pool.
conn.close()


当它被垃圾回收时,代理还会将其包含的 DBAPI 连接返回到池中,尽管在 Python 中并不确定这会立即发生(尽管这在 cPython 中很常见)。但是,不建议使用这种用法,特别是 asyncio DBAPI 驱动程序不支持这种用法。


返回时重置


该池包含“return 时重置”行为,该行为将调用 rollback() 方法。 这样,任何现有的事务状态都会从 connection,其中不仅包括未提交的数据,还包括 table 和 row 锁 井。对于大多数 DBAPI,对 rollback() 的调用成本低廉,如果 DBAPI 已经完成了事务,则该方法应该是无作方法。


为非事务性连接禁用 Return 时重置


对于此 rollback() 没有用的非常特殊的情况,例如 使用配置为 autocommit 或使用数据库时 没有 ACID 功能(如 MySQL 的 MyISAM 引擎)、 可以禁用 reset-on-return 行为,这通常是为了 性能原因。这可能会受到使用 Pool.reset_on_return Pool 的参数,也可以从 create_engine() 获得,如 create_engine.pool_reset_on_return ,传递值 None。 下面的示例将对此进行说明,并将其与 create_engine.isolation_level 参数设置 自动提交

non_acid_engine = create_engine(
    "mysql://scott:tiger@host/db",
    pool_reset_on_return=None,
    isolation_level="AUTOCOMMIT",
)


当连接返回到池中时,上述引擎实际上不会执行 ROLLBACK;由于启用了 AUTOCOMMIT,因此驱动程序也不会执行任何 BEGIN作。


自定义 Reset-on-Return 方案


对于某些用例,由单个 rollback() 组成的 “reset on return” 可能不够;特别是,使用临时 table 的应用程序可能希望在 Connection Checkin 时自动删除这些 table。一些(但值得注意的是不是全部)后端包含可以在数据库连接范围内“重置”此类表的功能,这可能是连接池重置的理想行为。其他服务器资源(例如准备好的语句句柄和服务器端语句缓存)可能会在签入过程之后仍然存在,这可能是可取的,也可能是不可取的,具体取决于具体情况。同样,一些(但不是全部)后端可能提供重置此状态的方法。已知具有此类重置方案的两个 SQLAlchemy 包含的方言包括 Microsoft SQL Server,其中经常使用一个未记录但广为人知的存储过程,称为 sp_reset_connection, 以及 PostgreSQL,它有一系列有据可查的命令,包括 DISCARDRESET、DEALLOCATEUNLISTEN。


以下示例说明了sp_reset_connection Microsoft如何使用 PoolEvents.reset() 事件钩子。这 create_engine.pool_reset_on_return parameter 设置为 None ,以便自定义方案可以完全替换默认行为。这 自定义钩子实现在任何情况下都会调用 .rollback(),因为 DBAPI 自己的提交/回滚跟踪与事务状态保持一致通常很重要:

from sqlalchemy import create_engine
from sqlalchemy import event

mssql_engine = create_engine(
    "mssql+pyodbc://scott:tiger^5HHH@mssql2017:1433/test?driver=ODBC+Driver+17+for+SQL+Server",
    # disable default reset-on-return scheme
    pool_reset_on_return=None,
)


@event.listens_for(mssql_engine, "reset")
def _reset_mssql(dbapi_connection, connection_record, reset_state):
    if not reset_state.terminate_only:
        dbapi_connection.execute("{call sys.sp_reset_connection}")

    # so that the DBAPI itself knows that the connection has been
    # reset
    dbapi_connection.rollback()


在 2.0.0b3 版本发生变更: PoolEvents.reset() 事件添加了额外的状态参数,并额外确保为所有 “reset” 事件调用该事件,以便它适合作为自定义 “reset” 处理程序的位置。以前使用 PoolEvents.checkin() 处理程序的方案也仍然可用。


记录 reset-on-return 事件


可以设置池事件的日志记录,包括返回时重置 伐木。调试 log 级别以及 sqlalchemy.pool 记录器,或者通过设置 create_engine.echo_pool 设置为“调试” create_engine() 中:

>>> from sqlalchemy import create_engine
>>> engine = create_engine("postgresql://scott:tiger@localhost/test", echo_pool="debug")


上述池将显示详细的日志记录,包括 reset on return:

>>> c1 = engine.connect()
DEBUG sqlalchemy.pool.impl.QueuePool Created new connection <connection object ...>
DEBUG sqlalchemy.pool.impl.QueuePool Connection <connection object ...> checked out from pool
>>> c1.close()
DEBUG sqlalchemy.pool.impl.QueuePool Connection <connection object ...> being returned to pool
DEBUG sqlalchemy.pool.impl.QueuePool Connection <connection object ...> rollback-on-return


矿池事件


连接池支持一个事件接口,该接口允许在第一次连接时、每个新连接时以及在连接签出和签入时执行 hooks。有关详细信息,请参阅 PoolEvents


处理断开连接


连接池能够刷新单个连接及其整个连接集,将之前池化的连接设置为 “invalid”。一个常见的用例是允许连接池在数据库服务器重新启动时正常恢复,并且所有以前建立的连接都不再有效。有两种方法可以解决这个问题。


断开连接处理 - 悲观


悲观方法是指在每个连接池检出开始时对 SQL 连接发出测试语句,以测试数据库连接是否仍然可行。该实现特定于方言,并使用特定于 DBAPI 的 ping 方法,或使用简单的 SQL 语句(如“SELECT 1”)来测试连接的活跃性。


这种方法会给连接签出过程增加一点开销,但除此之外,它是完全消除由于过时的池连接而导致的数据库错误的最简单可靠的方法。调用应用程序无需担心组织作,以便能够从池中签出的过时连接中恢复。


结账时对连接进行悲观测试可以通过使用 Pool.pre_ping 参数来实现,该参数可从 create_engine() 获得 通过 create_engine.pool_pre_ping 参数:

engine = create_engine("mysql+pymysql://user:pw@host/db", pool_pre_ping=True)


“pre ping”功能通过调用特定于 DBAPI 的“ping”方法在每种方言的基础上运行,或者如果不可用,将发出相当于“SELECT 1”的 SQL,捕获任何错误并将错误检测为“断开连接”情况。如果 ping / 错误检查确定该连接不可用,则会立即回收该连接,并且所有其他早于当前时间的池连接都将失效,以便下次检出时,它们也将在使用前被回收。


如果在 “pre ping” 运行时数据库仍然不可用,则初始连接将失败,并且连接失败的错误将正常传播。在数据库可用于连接但无法响应“ping”的罕见情况下,“pre_ping”将在放弃之前尝试最多三次,从而传播上次收到的数据库错误。


请务必注意,预 ping 方法不适用于 连接在事务或其他 SQL作过程中断开。如果 当事务正在进行时,数据库变得不可用,则 事务将丢失,并引发数据库错误。 虽然 Connection 对象将检测到 “disconnect” 情况,并且 回收连接并使连接池的其余部分无效 出现此情况时,异常所在的单个作 raised 将丢失,并且由应用程序放弃 作,或者再次重试整个事务。 如果发动机是 使用 DBAPI 级别的自动提交连接进行配置,如 设置事务隔离级别(包括 DBAPI 自动提交),可以在作过程中使用事件透明地重新连接连接。有关示例,请参阅如何自动“重试”语句执行?部分。


对于使用 “SELECT 1” 并捕获错误以检测断开连接的方言,可以使用 DialectEvents.handle_error() 钩子为新的特定于后端的错误消息增强断开连接测试。


自定义 / 遗留悲观 Ping


在添加 create_engine.pool_pre_ping 之前,“pre-ping”方法以前是使用 ConnectionEvents.engine_connect() engine 事件手动执行的。最常见的 recipe 如下,以供参考,以防应用程序已经在使用这样的 recipe,或者需要特殊行为:

from sqlalchemy import exc
from sqlalchemy import event
from sqlalchemy import select

some_engine = create_engine(...)


@event.listens_for(some_engine, "engine_connect")
def ping_connection(connection, branch):
    if branch:
        # this parameter is always False as of SQLAlchemy 2.0,
        # but is still accepted by the event hook.  In 1.x versions
        # of SQLAlchemy, "branched" connections should be skipped.
        return

    try:
        # run a SELECT 1.   use a core select() so that
        # the SELECT of a scalar value without a table is
        # appropriately formatted for the backend
        connection.scalar(select(1))
    except exc.DBAPIError as err:
        # catch SQLAlchemy's DBAPIError, which is a wrapper
        # for the DBAPI's exception.  It includes a .connection_invalidated
        # attribute which specifies if this connection is a "disconnect"
        # condition, which is based on inspection of the original exception
        # by the dialect in use.
        if err.connection_invalidated:
            # run the same SELECT again - the connection will re-validate
            # itself and establish a new connection.  The disconnect detection
            # here also causes the whole connection pool to be invalidated
            # so that all stale connections are discarded.
            connection.scalar(select(1))
        else:
            raise


上述方法的优点是,我们利用 SQLAlchemy 的工具来检测那些已知指示 “断开连接” 情况的 DBAPI 异常,以及 Engine 对象在发生这种情况时正确使当前连接池失效的能力,并允许当前 Connection 重新验证到新的 DBAPI 连接上。


断开连接处理 - 乐观


当未采用悲观处理时,以及当数据库被 在 事务,处理过时/关闭连接的另一种方法是 让 SQLAlchemy 在断开连接时处理它们,此时所有 池中的连接将失效,这意味着它们被假定为 陈旧的,并将在下次结账时刷新。 此行为假定 PoolEngine 结合使用。Engine 具有可以检测断开连接事件并自动刷新池的逻辑。


Connection 尝试使用 DBAPI 连接,并引发与“disconnect”事件相对应的异常时,该连接将失效。然后,Connection 调用 Pool.recreate() 方法,有效地使当前未签出的所有连接失效 下次结帐时,它们将被新的替换。 此流程为 由下面的代码示例说明:

from sqlalchemy import create_engine, exc

e = create_engine(...)
c = e.connect()

try:
    # suppose the database has been restarted.
    c.execute(text("SELECT * FROM table"))
    c.close()
except exc.DBAPIError as e:
    # an exception is raised, Connection is invalidated.
    if e.connection_invalidated:
        print("Connection was invalidated!")

# after the invalidate event, a new connection
# starts with a new Pool
c = e.connect()
c.execute(text("SELECT * FROM table"))


上面的示例说明了刷新池不需要特殊干预,在检测到断开连接事件后,刷新池会正常继续。但是,在发生数据库不可用事件时,每个正在使用的每个连接都会引发一个数据库异常。在使用 ORM 会话的典型 Web 应用程序中,上述条件对应于单个请求失败并出现 500 错误,然后 Web 应用程序在此之后继续正常进行。因此,该方法是 “乐观的” ,因为预计不会频繁地重新启动数据库。


设置 Pool Recycle


可以增强 “乐观” 方法的另一个设置是设置 pool recycle 参数。此参数可防止池使用已超过特定期限的特定连接,并且适用于数据库后端(如 MySQL),这些后端会在特定时间段后自动关闭已过时的连接:

from sqlalchemy import create_engine

e = create_engine("mysql+mysqldb://scott:tiger@localhost/test", pool_recycle=3600)


在上面,任何已打开超过一小时的 DBAPI 连接都将失效,并在下次结帐时被替换。请注意,失效仅在签出期间发生 - 不发生在保持签出状态的任何连接上。pool_recyclePool 本身的函数,与是否使用 Engine 无关。


更多关于失效的信息¶


提供“连接失效”服务,该服务允许对连接进行显式失效,以及在确定导致连接不可用的情况下自动失效。


“失效”是指从池中删除并丢弃特定的 DBAPI 连接。如果不清楚连接本身可能未关闭,则在此连接上调用 .close() 方法,但是如果此方法失败,则会记录异常,但作仍在继续。


使用 Engine 时,Connection.invalidate() 方法是显式失效的常用入口点。DBAPI 连接可能失效的其他条件包括:


  • 在调用 connection.execute() 等方法时引发的 DBAPI 异常(如 OperationalError)被检测为指示所谓的“断开连接”情况。由于 Python DBAPI 没有提供用于确定异常性质的标准系统,因此所有 SQLAlchemy 方言都包含一个名为 is_disconnect() 的系统,该系统将检查异常对象的内容,包括字符串消息和其中包含的任何潜在错误代码,以确定此异常是否表明该连接不再可用。如果是这种情况,则调用 _ConnectionFairy.invalidate() 方法,然后丢弃 DBAPI 连接。


  • 当连接返回到池中时,调用 connection.rollback()connection.commit() 方法(如池的“return 时重置”行为所指示)会引发异常。将最后一次尝试在连接上调用 .close(),然后将其丢弃。


  • 当实现 PoolEvents.checkout() 的侦听器引发 DisconnectionError 异常,表示该连接将不可用,需要进行新的连接尝试。


发生的所有失效都将调用 PoolEvents.invalidate() 事件。


支持新的数据库错误代码,用于断开连接场景


SQLAlchemy 方言都包含一个名为 is_disconnect() 的例程,即 每当遇到 DBAPI 异常时调用。DBAPI 异常对象 传递给此方法,然后特定于方言的启发式方法将确定 如果收到的错误代码指示数据库连接已 “disconnected”,或者处于其他不可用状态,这表明它应该 被回收利用。此处应用的启发式方法可以使用 DialectEvents.handle_error() 事件钩子,通常通过拥有的 Engine 对象建立。使用这个钩子,所有 发生的错误会传递一个上下文对象,称为 ExceptionContext 的 ExceptionContext 中。自定义事件钩子可以控制是否应将特定错误视为 “断开连接” 情况,以及此断开连接是否应导致整个连接池失效。


例如,要添加支持以考虑 Oracle Database 驱动程序错误代码 DPY-1001DPY-4011 作为断开连接代码处理,请在创建后将事件处理程序应用于引擎:

import re

from sqlalchemy import create_engine

engine = create_engine(
    "oracle+oracledb://scott:tiger@localhost:1521?service_name=freepdb1"
)


@event.listens_for(engine, "handle_error")
def handle_exception(context: ExceptionContext) -> None:
    if not context.is_disconnect and re.match(
        r"^(?:DPY-1001|DPY-4011)", str(context.original_exception)
    ):
        context.is_disconnect = True

    return None


对于引发的所有 Oracle Database 错误,包括对依赖于断开连接错误处理的后端(2.0 中的新增功能)使用池预 ping 功能时捕获的错误,将调用上述错误处理函数。


使用 FIFO 与 LIFO¶


QueuePool 类具有一个名为 QueuePool.use_lifo,也可以从 create_engine() 通过标志 create_engine.pool_use_lifo。将此标志设置为 True 会导致池的“队列”行为变为“堆栈”的行为,例如,要返回到池的最后一个连接是下一个请求使用的第一个连接。与池长期以来的先进先出行为相反,该行为会产生串联使用池中的每个连接的循环效应,而 lifo 模式允许多余的连接在池中保持空闲状态,从而允许服务器端超时方案关闭这些连接。FIFO 和 LIFO 之间的区别基本上是池是否希望即使在空闲期间也能保持一整套连接准备就绪:

engine = create_engine("postgreql://", pool_use_lifo=True, pool_pre_ping=True)


在上面,我们还使用了 create_engine.pool_pre_ping 标志,以便连接池可以正常处理从服务器端关闭的连接,并替换为新连接。


请注意,该标志仅适用于 QueuePool 使用。


在 1.3 版本加入.


另请参阅


处理断开连接


通过 Multiprocessing 或 os.fork() 使用连接池


在使用连接池时,以及使用通过 create_engine() 创建的 Engine 时,池连接不会共享给分叉的进程,这一点至关重要。TCP 连接表示为文件描述符,通常跨进程边界工作,这意味着这将导致代表两个或多个完全独立的 Python 解释器状态对文件描述符的并发访问。


根据驱动程序和作系统的具体情况,这里出现的问题范围从不工作的连接到多个进程同时使用的套接字连接,从而导致消息传递中断(后一种情况通常是最常见的)。


SQLAlchemy Engine 对象引用现有数据库连接的连接池。因此,当此对象复制到子进程时,目标是确保没有数据库连接被转移。有四种常规方法:


  1. 使用 NullPool 禁用池化。这是最简单的一次性系统,可防止 Engine 多次使用任何连接:

    from sqlalchemy.pool import NullPool
    
    engine = create_engine("mysql+mysqldb://user:pass@host/dbname", poolclass=NullPool)

  2. 在任何给定的 Engine 上调用 Engine.dispose(),传递值为 False,则在子进程的 initialize 阶段。 这是 这样新进程就不会触及父进程的任何连接 而是从新的连接开始。 这是推荐的方法

    from multiprocessing import Pool
    
    engine = create_engine("mysql+mysqldb://user:pass@host/dbname")
    
    
    def run_in_process(some_data_record):
        with engine.connect() as conn:
            conn.execute(text("..."))
    
    
    def initializer():
        """ensure the parent proc's database connections are not touched
        in the new connection pool"""
        engine.dispose(close=False)
    
    
    with Pool(10, initializer=initializer) as p:
        p.map(run_in_process, data)


    1.4.33 版本中的新功能: 添加了 Engine.dispose.close 参数以允许替换子节点中的连接池 进程而不干扰父级使用的连接 过程。


  3. 在创建子进程之前直接调用 Engine.dispose()。这也将导致子进程从新的连接池开始,同时确保父连接不会转移到子进程:

    engine = create_engine("mysql://user:pass@host/dbname")
    
    
    def run_in_process():
        with engine.connect() as conn:
            conn.execute(text("..."))
    
    
    # before process starts, ensure engine.dispose() is called
    engine.dispose()
    p = Process(target=run_in_process)
    p.start()

  4. 事件处理程序可以应用于连接池,用于测试跨进程边界共享的连接,并使它们失效:

    from sqlalchemy import event
    from sqlalchemy import exc
    import os
    
    engine = create_engine("...")
    
    
    @event.listens_for(engine, "connect")
    def connect(dbapi_connection, connection_record):
        connection_record.info["pid"] = os.getpid()
    
    
    @event.listens_for(engine, "checkout")
    def checkout(dbapi_connection, connection_record, connection_proxy):
        pid = os.getpid()
        if connection_record.info["pid"] != pid:
            connection_record.dbapi_connection = connection_proxy.dbapi_connection = None
            raise exc.DisconnectionError(
                "Connection record belongs to pid %s, "
                "attempting to check out in pid %s" % (connection_record.info["pid"], pid)
            )


    上面,我们使用了一种类似于 断开连接处理 - 悲观地将源自不同父进程的 DBAPI 连接视为“无效”连接,强制池回收连接记录以建立新连接。


上述策略将适应 Engine 的情况 在进程之间共享。仅靠上述步骤不足以完成 在进程边界上共享特定 Connection 的情况;更喜欢将特定 Connection 的范围保留在单个进程(和线程)的本地。此外,不支持直接跨进程边界共享任何类型的正在进行的事务状态,例如已开始事务并引用活动 Connection 实例的 ORM Session 对象;再次首选创建新的 Session 对象。


直接使用 pool 实例


池实现可以直接使用,无需引擎。这可用于只希望使用池行为而没有所有其他 SQLAlchemy 功能的应用程序。在下面的示例中,MySQLdb 方言的默认池是使用 create_pool_from_url() 中:

from sqlalchemy import create_pool_from_url

my_pool = create_pool_from_url(
    "mysql+mysqldb://", max_overflow=5, pool_size=5, pre_ping=True
)

con = my_pool.connect()
# use the connection
...
# then close it
con.close()


如果未指定要创建的池类型,则将使用方言的默认池类型。要直接指定它,可以使用 poolclass 参数,如下例所示:

from sqlalchemy import create_pool_from_url
from sqlalchemy import NullPool

my_pool = create_pool_from_url("mysql+mysqldb://", poolclass=NullPool)


API 文档 - 可用的矿池实现


对象名称

描述

_ConnectionFairy


代理 DBAPI 连接并提供取消引用时返回支持。

_ConnectionRecord


在引用池化连接的连接池中维护一个位置。


断言池


在任何给定时间最多允许一个签出连接的 Pool

AsyncAdaptedQueuePool


QueuePool 的 asyncio 兼容版本。

ConnectionPoolEntry


代表 Pool 实例维护单个数据库连接的对象的接口。


管理连接


两个连接管理接口的通用基础 PoolProxiedConnectionConnectionPoolEntry 的 PoolEntry


空池


不池连接的 Pool。



连接池的抽象基类。


PoolProxiedConnection (池代理连接)


用于 PEP 249 DBAPI 连接的类似连接的适配器,其中包括特定于 Pool 实现的其他方法。


队列池


A 泳池 这会对打开的连接数施加限制。

SingletonThreadPool


一个 Pool,它为每个线程维护一个连接。


静态池


一个 Pool 只有一个连接,用于所有请求。


sqlalchemy.pool 中。矿池


连接池的抽象基类。


类签名


sqlalchemy.pool.Poolsqlalchemy.log.已识别sqlalchemy.event.registry.EventTarget


方法 sqlalchemy.pool.Pool 中。__init__creator:_CreatorFnType_CreatorWRecFnType, recycle int = -1echo log._EchoFlagType = None, logging_name:strNone=None,reset_on_return:_ResetStyleArgType = True,事件:List[Tuple[_ListenerFnType,str]]None=无,dialect:_ConnDialectDialectNone=无,pre_ping:bool = False, _dispatch:_DispatchCommon[Pool]None=None)


构造一个池。


参数

  • creator——返回 DB-API 连接对象的可调用函数。该函数将使用参数调用。


  • 回收– 如果设置为非 -1 的值,则连接回收之间的秒数,这意味着在签出时,如果超过此超时,连接将被关闭并替换为新打开的连接。默认为 -1。


  • logging_name– 字符串标识符,将在 “sqlalchemy.pool” 记录器中生成的日志记录的 “name” 字段中使用。默认为对象 id 的十六进制字符串。


  • 回声


    如果为 True,则连接池将记录信息输出,例如连接何时失效以及连接何时回收到默认日志处理程序,默认为 sys.stdout 输出。 如果设置为字符串 “debug”,则日志记录将包括池签出和签入。


    Pool.echo 参数也可以从 create_engine() 调用 create_engine.echo_pool 参数。


    另请参阅


    配置日志记录 - 有关如何配置日志记录的更多详细信息。

  • reset_on_return


    确定在连接返回到池时要对连接采取的步骤,这些连接不会由 Connection 处理。可通过 create_engine() 获取 create_engine.pool_reset_on_return 参数。


    Pool.reset_on_return 可以具有以下任何值:


    • “rollback” - 在连接上调用 rollback() 以释放锁和事务资源。这是默认值。绝大多数用例应保留此值集。


    • “commit” - 在连接上调用 commit() 以释放锁和事务资源。对于在发出提交时缓存查询计划的数据库(例如 Microsoft SQL Server),此处的提交可能是可取的。但是,此值比 'rollback' 更危险,因为事务中存在的任何数据更改都是无条件提交的。


    • - 不对连接执行任何作。 如果数据库/DBAPI 始终在纯 “autocommit” 模式下工作,或者如果 自定义重置处理程序是使用 PoolEvents.reset() 事件处理程序。


    • True - 与 'rollback' 相同,这是为了向后兼容。


    • False - 与 None 相同,这是为了向后兼容。


    要进一步自定义 reset on return,请使用 可以使用 PoolEvents.reset() 事件钩子,它可以执行重置时所需的任何连接活动。


  • events —— 一个 2 元组的列表,每个元组的形式 (callable, target),它将被传递给 listen() 在施工时。 因此,事件侦听器 可以在应用 dialect 级别的侦听器之前通过 create_engine() 进行分配。


  • dialect– 一种 Dialect,它将处理在 DBAPI 连接上调用 rollback()、close() 或 commit() 的工作。如果省略,则使用内置的 “stub” 方言。使用 create_engine() 的应用程序不应使用此参数,因为它由引擎创建策略处理。

  • pre_ping


    如果为 True,则池将在签出时对连接发出“ping”(通常为“SELECT 1”,但特定于方言),以测试连接是否处于活动状态。否则,将透明地重新连接连接,成功后,在该时间戳之前建立的所有其他池连接都将失效。要求同时传递方言来解释断开连接错误。


    在 1.2 版本加入.


方法 sqlalchemy.pool.Pool 中。connect PoolProxiedConnection


从池中返回 DBAPI 连接。


该连接被检测为,当其 close() 方法,则连接将返回到池中。


方法 sqlalchemy.pool.Pool 中。dispose


处理此池。


此方法使签出连接保持打开状态,因为它只影响池中处于空闲状态的连接。


另请参阅


Pool.recreate()


方法 sqlalchemy.pool.Pool 中。recreate Pool


返回一个新的 Pool,该 Pool 与此 Pool 具有相同的类,并配置了相同的创建参数。


此方法与 dispose() 结合使用 以关闭整个池并在其位置创建一个新


sqlalchemy.pool 中。队列池


A 泳池 这会对打开的连接数施加限制。


QueuePool 是用于除 SQLite 之外的所有 Engine 对象的默认池实现,带有 :memory: 数据库。


QueuePool 类与 asyncio 和 create_async_engine() 中。 这 如果未指定其他类型的池,则在使用 create_async_engine() 时自动使用 AsyncAdaptedQueuePool 类。


另请参阅

AsyncAdaptedQueuePool


方法 sqlalchemy.pool.QueuePool 中。__init__creator:_CreatorFnType_CreatorWRecFnType, pool_size int = 5max_overflow: int = 10timeout float = 30.0use_lifo: bool = False**kw Any


构造 QueuePool。


参数

  • creator– 一个可调用的函数,返回一个 DB-API 连接对象,与 Pool.creator 相同。


  • pool_size – 要维护的矿池的大小, 默认为 5。这是 将永久保留在池中。请注意,池 从没有连接开始;一旦此连接数 请求时,将保留该数量的连接。 pool_size 可以设置为 0 以表示没有大小限制;要禁用池化,请使用 NullPool 相反。


  • max_overflow– 最大溢出大小的 池。当签出的连接数达到 size 设置为 pool_size,则额外的连接将为 返回到此限制。当这些额外的连接 返回到池中,则断开连接,并且 丢弃。因此,总数 池允许的并发连接数为 pool_size + max_overflow,并且池将允许的 “休眠” 连接总数为 pool_size。max_overflow 可以设置为 -1 以表示无溢出限制;无限制 将放置在并发总数上 连接。默认值为 10。


  • timeout— 在放弃返回连接之前等待的秒数。默认为 30.0。这可以是浮点数,但受 Python 时间函数的限制,在几十毫秒内可能不可靠。

  • use_lifo


    检索连接时使用 LIFO (后进先出) 而不是 FIFO (先进先出)。使用 LIFO,服务器端超时方案可以减少非高峰使用期间使用的连接数。在规划服务器端超时时,请确保使用回收或 pre-ping 策略来正常处理过时的连接。


    在 1.3 版本加入.


  • kw– 其他关键字参数,包括 Pool.recyclePool.echoPool.reset_on_return 和其他 API 将传递给 Pool 构造函数。


方法 sqlalchemy.pool.QueuePool 中。dispose


处理此池。


此方法使签出连接保持打开状态,因为它只影响池中处于空闲状态的连接。


另请参阅


Pool.recreate()


方法 sqlalchemy.pool.QueuePool 中。recreate QueuePool


返回一个新的 Pool,该 Pool 与此 Pool 具有相同的类,并配置了相同的创建参数。


此方法与 dispose() 结合使用 以关闭整个池并在其位置创建一个新


sqlalchemy.pool 中。AsyncAdaptedQueuePool


QueuePool 的 asyncio 兼容版本。


当使用从 create_async_engine() 生成的 AsyncEngine 引擎时,默认使用此池。 它使用 asyncio 兼容的队列实现,该实现不使用 线程。锁定


AsyncAdaptedQueuePool 的参数和作与 QueuePool 的参数和作相同。


sqlalchemy.pool 中。SingletonThreadPool(单例线程池)¶


一个 Pool,它为每个线程维护一个连接。


为每个线程维护一个连接,从不将连接移动到创建该连接的线程以外的线程。


警告


SingletonThreadPool 将调用 .close() 在超出 size 设置的任意连接上 pool_size,例如,如果线程标识具有更多唯一 比使用pool_size状态。此清理是不确定的,并且对链接到这些线程身份的连接当前是否正在使用不敏感。


SingletonThreadPool 可能会在将来的版本中得到改进,但在当前状态下,它通常仅用于使用 SQLite :memory: 数据库的测试场景,不建议用于生产环境。


SingletonThreadPool 类与 asyncio 和 create_async_engine() 不兼容


选项与 Pool 的选项相同,并且:


参数


pool_size– 一次保持连接的线程数。默认为 5。


当使用基于内存的数据库时,SQLite 方言会自动使用 SingletonThreadPool。请参阅 SQLite


方法 sqlalchemy.pool.SingletonThreadPool. connect)→ PoolProxiedConnection


从池中返回 DBAPI 连接。


该连接被检测为,当其 close() 方法,则连接将返回到池中。


方法 sqlalchemy.pool.SingletonThreadPool. dispose None


处理此池。


方法 sqlalchemy.pool.SingletonThreadPool. recreate SingletonThreadPool


返回一个新的 Pool,该 Pool 与此 Pool 具有相同的类,并配置了相同的创建参数。


此方法与 dispose() 结合使用 以关闭整个池并在其位置创建一个新


sqlalchemy.pool 中。AssertionPool(断言池)¶


在任何给定时间最多允许一个签出连接的 Pool


如果一次签出多个连接,这将引发异常。对于调试使用比所需连接数更多的代码很有用。


AssertionPool 类与 asyncio 和 create_async_engine() 中。


方法 sqlalchemy.pool.AssertionPool. dispose None


处理此池。


此方法使签出连接保持打开状态,因为它只影响池中处于空闲状态的连接。


另请参阅


Pool.recreate()


方法 sqlalchemy.pool.AssertionPool. recreate AssertionPool


返回一个新的 Pool,该 Pool 与此 Pool 具有相同的类,并配置了相同的创建参数。


此方法与 dispose() 结合使用 以关闭整个池并在其位置创建一个新


sqlalchemy.pool 中。空池


不池连接的 Pool。


相反,它实际上是在每次打开/关闭每个连接时打开和关闭底层 DB-API 连接。


此 Pool 实现不支持与 Reconnect 相关的功能,例如 recycle 和 connection invalidation,因为没有持续保留任何连接。


NullPool 类与 asyncio 和 create_async_engine() 中。


方法 sqlalchemy.pool.NullPool 中。dispose


处理此池。


此方法使签出连接保持打开状态,因为它只影响池中处于空闲状态的连接。


另请参阅


Pool.recreate()


方法 sqlalchemy.pool.NullPool 中。recreate NullPool


返回一个新的 Pool,该 Pool 与此 Pool 具有相同的类,并配置了相同的创建参数。


此方法与 dispose() 结合使用 以关闭整个池并在其位置创建一个新


sqlalchemy.pool 中。静态池


一个 Pool 只有一个连接,用于所有请求。


与 Reconnect 相关的功能,例如 recycle 和 connection invalidation(也用于支持自动重新连接)目前仅部分支持,可能不会产生良好的结果。


StaticPool 类与 asyncio 和 create_async_engine() 中。


方法 sqlalchemy.pool.StaticPool 中。dispose


处理此池。


此方法使签出连接保持打开状态,因为它只影响池中处于空闲状态的连接。


另请参阅


Pool.recreate()


方法 sqlalchemy.pool.StaticPool 中。recreate StaticPool


返回一个新的 Pool,该 Pool 与此 Pool 具有相同的类,并配置了相同的创建参数。


此方法与 dispose() 结合使用 以关闭整个池并在其位置创建一个新


sqlalchemy.pool 中。ManagesConnection(管理连接)¶


两个连接管理接口的通用基础 PoolProxiedConnectionConnectionPoolEntry 的 PoolEntry


这两个对象通常通过连接池事件钩子在面向公众的 API 中公开,记录在 PoolEvents 中。


2.0 版的新Function。


属性 sqlalchemy.pool.ManagesConnection. dbapi_connection:D BAPIConnectionNone


对正在跟踪的实际 DBAPI 连接的引用。


这是一个符合 PEP 249 的对象,对于传统的同步样式 dialects 由第三方提供 正在使用的 DBAPI 实现。 对于 asyncio dialects,实现 通常是 SQLAlchemy 方言提供的适配器对象 本身;底层 asyncio 对象可通过 ManagesConnection.driver_connection 属性。


SQLAlchemy 的 DBAPI 连接接口基于 DBAPIConnection 协议对象


属性 sqlalchemy.pool.ManagesConnection. driver_connection:AnyNone


Python DBAPI 或数据库驱动程序使用的“驱动程序级别”连接对象。


对于传统的 PEP 249 DBAPI 实现,此对象将 与 的对象相同 ManagesConnection.dbapi_connection 。对于 asyncio 数据库驱动程序,这将是该驱动程序使用的最终 “connection” 对象,例如 asyncpg。Connection 对象,该对象将没有标准的 pep-249 方法。


在 1.4.24 版本加入.


属性 sqlalchemy.pool.ManagesConnection. 信息


与此 ManagesConnection 实例引用的基础 DBAPI 连接关联的信息字典,允许用户定义的数据与连接相关联。


此字典中的数据在 DBAPI 连接本身的生命周期内是持久的,包括跨池签入和签出。当连接失效并替换为新连接时,将清除此字典。


对于未与 ConnectionPoolEntry 关联的 PoolProxiedConnection 实例(例如,如果它已分离),则 attribute 返回一个本地字典 ConnectionPoolEntry 的 ConnectionPoolEntry 中。因此, ManagesConnection.info 属性将始终提供 Python 字典。


method sqlalchemy.pool.ManagesConnection. invalidatee:BaseExceptionNone=None, soft bool = False None


将托管连接标记为无效。


参数

  • e —— 一个异常对象,指示失效的原因。


  • soft —— 如果为 True,则连接未关闭;相反,此连接将在下次结帐时回收。


属性 sqlalchemy.pool.ManagesConnection. record_info


与此关联的持久信息字典 ManagesConnection 的 ManagesConnection 中。


ManagesConnection.info 字典不同,此字典的生存期是 ConnectionPoolEntry 的生存期 谁拥有它;因此,此字典将在 特定条目的重新连接和连接失效 在连接池中。


对于未与 ConnectionPoolEntry 关联的 PoolProxiedConnection 实例(例如,如果它已分离),该属性将返回 None。与 ManagesConnection.info 形成对比 dictionary 中,它永远不会是 None。


另请参阅

ManagesConnection.info


sqlalchemy.pool 中。ConnectionPoolEntry


代表 Pool 实例维护单个数据库连接的对象的接口。


ConnectionPoolEntry 对象表示池的特定连接的长期维护,包括使该连接过期或失效,以将其替换为新连接,该连接将继续由同一 ConnectionPoolEntry 维护 实例。与 PoolProxiedConnection 相比,PoolProxiedConnection 是短期的每次签出连接管理器,此对象在连接池中特定 “slot” 的生命周期内持续存在。


ConnectionPoolEntry 对象对面向公众的大多数情况下是可见的 API 代码(当它被投递到连接池事件钩子时,例如 PoolEvents.connect()PoolEvents.checkout() 的 PoolEvents.checkout() 进行访问。


2.0 版中的新功能: ConnectionPoolEntry_ConnectionRecord 内部类提供面向公众的接口。


方法 sqlalchemy.pool.ConnectionPoolEntry. close None


关闭由此连接池条目管理的 DBAPI 连接。


属性 sqlalchemy.pool.ConnectionPoolEntry. dbapi_connection:D BAPIConnectionNone


对正在跟踪的实际 DBAPI 连接的引用。


这是一个符合 PEP 249 的对象,对于传统的同步样式 dialects 由第三方提供 正在使用的 DBAPI 实现。 对于 asyncio dialects,实现 通常是 SQLAlchemy 方言提供的适配器对象 本身;底层 asyncio 对象可通过 ManagesConnection.driver_connection 属性。


SQLAlchemy 的 DBAPI 连接接口基于 DBAPIConnection 协议对象


属性 sqlalchemy.pool.ConnectionPoolEntry. driver_connection:AnyNone


Python DBAPI 或数据库驱动程序使用的“驱动程序级别”连接对象。


对于传统的 PEP 249 DBAPI 实现,此对象将 与 的对象相同 ManagesConnection.dbapi_connection 。对于 asyncio 数据库驱动程序,这将是该驱动程序使用的最终 “connection” 对象,例如 asyncpg。Connection 对象,该对象将没有标准的 pep-249 方法。


在 1.4.24 版本加入.


属性 sqlalchemy.pool.ConnectionPoolEntry. in_use


返回 True,表示连接当前已签出


属性 sqlalchemy.pool.ConnectionPoolEntry. 信息


继承自ManagesConnectionManagesConnection.info属性


与此 ManagesConnection 实例引用的基础 DBAPI 连接关联的信息字典,允许用户定义的数据与连接相关联。


此字典中的数据在 DBAPI 连接本身的生命周期内是持久的,包括跨池签入和签出。当连接失效并替换为新连接时,将清除此字典。


对于未与 ConnectionPoolEntry 关联的 PoolProxiedConnection 实例(例如,如果它已分离),则 attribute 返回一个本地字典 ConnectionPoolEntry 的 ConnectionPoolEntry 中。因此, ManagesConnection.info 属性将始终提供 Python 字典。


method sqlalchemy.pool.ConnectionPoolEntry. invalidatee:BaseExceptionNone=None, soft bool = False None


继承自 ManagesConnection.invalidate() ManagesConnection 的方法


将托管连接标记为无效。


参数

  • e —— 一个异常对象,指示失效的原因。


  • soft —— 如果为 True,则连接未关闭;相反,此连接将在下次结帐时回收。


属性 sqlalchemy.pool.ConnectionPoolEntry. record_info


继承自ManagesConnectionManagesConnection.record_info属性


与此关联的持久信息字典 ManagesConnection 的 ManagesConnection 中。


ManagesConnection.info 字典不同,此字典的生存期是 ConnectionPoolEntry 的生存期 谁拥有它;因此,此字典将在 特定条目的重新连接和连接失效 在连接池中。


对于未与 ConnectionPoolEntry 关联的 PoolProxiedConnection 实例(例如,如果它已分离),该属性将返回 None。与 ManagesConnection.info 形成对比 dictionary 中,它永远不会是 None。


另请参阅

ManagesConnection.info


sqlalchemy.pool 中。PoolProxiedConnection(池代理连接)¶


用于 PEP 249 DBAPI 连接的类似连接的适配器,其中包括特定于 Pool 实现的其他方法。


PoolProxiedConnection 是内部 _ConnectionFairy 实现对象的面向公众的接口;熟悉 _ConnectionFairy 的用户可以将此对象视为等效对象。


2.0 版中的新功能: PoolProxiedConnection_ConnectionFairy 内部类提供面向公众的接口。


方法 sqlalchemy.pool.PoolProxiedConnection. close None


将此连接释放回池中。


PoolProxiedConnection.close() 方法隐藏了 PEP 249.close() 方法,将其行为更改为 代理连接释放回连接池。


释放到池后,连接是在 Python 进程中保持“打开”和池化状态,还是实际关闭并从 Python 进程中删除,取决于正在使用的池实现及其配置和当前状态。


属性 sqlalchemy.pool.PoolProxiedConnection. dbapi_connection:D BAPIConnectionNone


对正在跟踪的实际 DBAPI 连接的引用。


这是一个符合 PEP 249 的对象,对于传统的同步样式 dialects 由第三方提供 正在使用的 DBAPI 实现。 对于 asyncio dialects,实现 通常是 SQLAlchemy 方言提供的适配器对象 本身;底层 asyncio 对象可通过 ManagesConnection.driver_connection 属性。


SQLAlchemy 的 DBAPI 连接接口基于 DBAPIConnection 协议对象


方法 sqlalchemy.pool.PoolProxiedConnection. detach


将此连接与其 Pool 分开。


这意味着连接在关闭时将不再返回到池中,而是将真正关闭。关联的 ConnectionPoolEntry 将与此 DBAPI 连接取消关联。


请注意,在分离后,可能会违反 Pool 实现施加的任何整体连接限制约束,因为分离的连接已从池的知识和控制中删除。


属性 sqlalchemy.pool.PoolProxiedConnection. driver_connection:AnyNone


Python DBAPI 或数据库驱动程序使用的“驱动程序级别”连接对象。


对于传统的 PEP 249 DBAPI 实现,此对象将 与 的对象相同 ManagesConnection.dbapi_connection 。对于 asyncio 数据库驱动程序,这将是该驱动程序使用的最终 “connection” 对象,例如 asyncpg。Connection 对象,该对象将没有标准的 pep-249 方法。


在 1.4.24 版本加入.


属性 sqlalchemy.pool.PoolProxiedConnection. 信息


继承自ManagesConnectionManagesConnection.info属性


与此 ManagesConnection 实例引用的基础 DBAPI 连接关联的信息字典,允许用户定义的数据与连接相关联。


此字典中的数据在 DBAPI 连接本身的生命周期内是持久的,包括跨池签入和签出。当连接失效并替换为新连接时,将清除此字典。


对于未与 ConnectionPoolEntry 关联的 PoolProxiedConnection 实例(例如,如果它已分离),则 attribute 返回一个本地字典 ConnectionPoolEntry 的 ConnectionPoolEntry 中。因此, ManagesConnection.info 属性将始终提供 Python 字典。


method sqlalchemy.pool.PoolProxiedConnection. invalidatee:BaseExceptionNone=None, soft bool = False None


继承自 ManagesConnection.invalidate() ManagesConnection 的方法


将托管连接标记为无效。


参数

  • e —— 一个异常对象,指示失效的原因。


  • soft —— 如果为 True,则连接未关闭;相反,此连接将在下次结帐时回收。


属性 sqlalchemy.pool.PoolProxiedConnection. is_detached


如果此 PoolProxiedConnection 与其池分离,则返回 True。


属性 sqlalchemy.pool.PoolProxiedConnection. is_valid


如果此 PoolProxiedConnection 仍引用活动的 DBAPI 连接,则返回 True。


属性 sqlalchemy.pool.PoolProxiedConnection. record_info


继承自ManagesConnectionManagesConnection.record_info属性


与此关联的持久信息字典 ManagesConnection 的 ManagesConnection 中。


ManagesConnection.info 字典不同,此字典的生存期是 ConnectionPoolEntry 的生存期 谁拥有它;因此,此字典将在 特定条目的重新连接和连接失效 在连接池中。


对于未与 ConnectionPoolEntry 关联的 PoolProxiedConnection 实例(例如,如果它已分离),该属性将返回 None。与 ManagesConnection.info 形成对比 dictionary 中,它永远不会是 None。


另请参阅

ManagesConnection.info


sqlalchemy.pool 中。_ConnectionFairy


代理 DBAPI 连接并提供取消引用时返回支持。


这是 Pool 实现使用的内部对象,用于为该 Pool 提供的 DBAPI 连接提供上下文管理。此类的面向公众的接口由 PoolProxiedConnection 类描述。有关公共 API 的详细信息,请参阅该类。


“fairy”这个名字的灵感来自于 _ConnectionFairy对象的生命周期是暂时的,因为它仅在从池中签出的特定 DBAPI 连接的长度内持续,此外,作为透明代理,它几乎是不可见的。


类签名


sqlalchemy.pool._ConnectionFairy sqlalchemy.pool.base.PoolProxiedConnection


sqlalchemy.pool 中。_ConnectionRecord


在引用池化连接的连接池中维护一个位置。


这是 Pool 实现使用的内部对象,用于为该 Pool 维护的 DBAPI 连接提供上下文管理。此类的面向公众的接口由 ConnectionPoolEntry 类描述。有关公共 API 的详细信息,请参阅该类。


类签名


sqlalchemy.pool._ConnectionRecord sqlalchemy.pool.base.ConnectionPoolEntry