连接池¶
连接池是一种标准技术,用于在内存中维护长时间运行的连接,以便有效地重用,并为应用程序可能同时使用的连接总数提供管理。
特别是对于服务器端Web应用程序,连接池是在内存中维护活动数据库连接“池”的标准方法,这些活动数据库连接在请求之间重复使用。
sqlAlchemy包括几个连接池实现,这些实现与 Engine . 它们还可以直接用于希望向其他普通DBAPI方法添加池的应用程序。
连接池配置¶
这个 Engine 返回的 create_engine() 在大多数情况下,函数具有 QueuePool 集成,预先配置了合理的池默认值。如果您阅读本节只是为了学习如何启用池-恭喜!你已经做完了。
最常见 QueuePool 优化参数可以直接传递到 create_engine() 作为关键字参数: pool_size , max_overflow , pool_recycle 和 pool_timeout . 例如::
engine = create_engine('postgresql://me@localhost/mydb',
pool_size=20, max_overflow=0)
在sqlite的情况下, SingletonThreadPool 或 NullPool 被方言选择以提供与sqlite线程和锁定模型的更大兼容性,并为sqlite“内存”数据库提供合理的默认行为,这些数据库将其整个数据集维护在单个连接的范围内。
所有的sqlAlchemy池实现都有一个共同点,即它们都没有“预创建”连接——所有的实现都要等到第一次使用后才能创建连接。此时,如果没有对更多连接发出额外的并发签出请求,则不会创建额外的连接。这就是为什么它对 create_engine() 默认为使用 QueuePool 大小为5,不考虑应用程序是否真的需要排队5个连接-只有当应用程序同时使用5个连接时,池才会增长到该大小,在这种情况下,使用小池是完全合适的默认行为。
切换池实现¶
使用不同类型游泳池的常用方法 create_engine() 是使用 poolclass 争论。此参数接受从 sqlalchemy.pool 模块,并为您处理构建池的详细信息。常用选项包括指定 QueuePool SQLite::
from sqlalchemy.pool import QueuePool
engine = create_engine('sqlite:///file.db', poolclass=QueuePool)
from sqlalchemy.pool import NullPool
engine = create_engine(
'postgresql+psycopg2://scott:tiger@localhost/test',
poolclass=NullPool)
建造游泳池¶
使用A 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 = conn.cursor()
cursor.execute("select foo")
透明代理的目的是截取 close() 调用,使其返回池,而不是关闭DBAPI连接:
# "close" the connection. Returns
# it to the pool.
conn.close()
当池被垃圾收集时,代理也会将其包含的DBAPI连接返回到池,尽管在Python中,这种情况不会立即发生(尽管这在CPython中很常见)。
这个 close() 步骤还执行调用 rollback() DBAPI连接的方法。这样就可以删除连接上的任何现有事务,不仅可以确保在下次使用时不会保留任何现有状态,还可以释放表和行锁以及删除任何独立的数据快照。可以使用禁用此行为 reset_on_return 选择权 Pool .
一个特定的预先创建的 Pool 通过将其传递给 pool 的参数 create_engine() ::
e = create_engine('postgresql://', pool=mypool)
池事件¶
连接池支持一个事件接口,允许钩子在第一次连接、每个新连接以及连接的签出和签入时执行。见 PoolEvents 有关详细信息。
处理断开连接¶
连接池能够刷新单个连接及其整个连接集,将以前的池连接设置为“无效”。一个常见的用例是,当数据库服务器重新启动时,允许连接池正常恢复,并且所有以前建立的连接都不再正常工作。有两种方法可以解决这个问题。
断开操作-悲观¶
悲观的方法是在每个连接池签出开始时对SQL连接发出测试语句,以测试数据库连接是否仍然可行。通常,这是一个类似“select 1”的简单语句,但也可以使用一些DBAPI特定的方法来测试连接的活跃性。
这种方法给连接签出过程增加了一点开销,但在其他方面,它是完全消除由于过时的池连接导致的数据库错误的最简单和可靠的方法。调用应用程序不需要关心如何组织操作,以便能够从池中签出的过时连接中恢复。
需要注意的是,预ping方法 不适用于在事务或其他SQL操作中丢弃的连接 . 如果在事务处理过程中数据库不可用,则事务将丢失并引发数据库错误。而 Connection 当连接断开时,会再次出现连接断开连接的情况。如果引擎是使用DBAPI级别的自动提交连接配置的,如中所述 设置事务隔离级别,包括DBAPI Autocommit ,一个连接 may 在操作过程中使用事件透明地重新连接。参见章节 如何自动“重试”语句执行? 举个例子。
engine = create_engine("mysql+pymysql://user:pw@host/db", pool_pre_ping=True)
每次从池中签出连接时,“pre-ping”功能通常会发出相当于“select 1”的SQL;如果出现检测为“disconnect”情况的错误,则该连接将立即被回收,并且所有其他比当前时间早的池连接都将失效,以便下次它们处于丢弃后,也会在使用前回收利用。
如果“预Ping”运行时数据库仍然不可用,则初始连接将失败,并且连接失败的错误将正常传播。在数据库可用于连接但无法响应“ping”的罕见情况下,“pre-ping”将在放弃前尝试最多三次,传播上次收到的数据库错误。
注解
“pre-ping”发出的“select 1”在连接池/方言的范围内调用,使用非常短的代码路径将python延迟降至最低。因此,本声明是 未记录在SQL Echo输出中 ,并且不会显示在SQLAlchemy的引擎日志中。
1.2 新版功能:增加了“预Ping”功能 Pool 班级。
自定义/传统悲观ping¶
之前 create_engine.pool_pre_ping 添加了“预Ping”方法,历史上使用 ConnectionEvents.engine_connect() 引擎事件。最常见的方法如下,以供参考,以防应用程序已经在使用此类方法,或者需要特殊行为&