38

我开发了一些自定义的类似 DAO 的类来满足我的项目的一些非常特殊的要求,这是一个不在任何类型的框架内运行的服务器端进程。

该解决方案效果很好,只是每次发出新请求时,我都会通过 MySQLdb.connect 打开一个新连接。

将其切换为在 python 中使用连接池的最佳“直接”解决方案是什么?我正在想象类似 Java 的 commons DBCP 解决方案。

该进程运行时间很长,并且有许多线程需要发出请求,但不是同时发出请求……特别是在短暂地写出大量结果之前,它们做了很多工作。

编辑添加:经过更多搜索后,我发现anitpool.py看起来不错,但由于我对 python 比较陌生,我想我只是想确保我没有错过更明显/更惯用/更好的解决方案。

4

8 回答 8

24

在 MySQL 中?

我想说不要打扰连接池。它们通常是麻烦的根源,并且对于 MySQL,它们不会为您带来您希望的性能优势。这条道路可能需要付出很多努力——政治上——因为在这个领域有很多关于连接池优势的最佳实践和教科书式的冗长。

连接池只是无状态应用程序(例如 HTTP 协议)的后 Web 时代和有状态的长寿命批处理应用程序的前 Web 时代之间的桥梁。由于在 web 前的数据库中连接非常昂贵(因为过去没有人关心建立连接需要多长时间),所以后 web 应用程序设计了这种连接池方案,以便每次点击都不会产生如此巨大的处理开销在 RDBMS 上。

由于 MySQL 更像是一个 Web 时代的 RDBMS,因此连接非常轻量级和快速。我为 MySQL 编写了许多根本不使用连接池的大容量 Web 应用程序。

只要没有需要克服的政治障碍,您可能会从不这样做中受益。

于 2008-09-19T04:11:38.877 回答
18

包装你的连接类。

限制您建立的连接数。返回未使用的连接。拦截关闭以释放连接。

更新:我在 dbpool.py 中放了这样的东西:

import sqlalchemy.pool as pool
import MySQLdb as mysql
mysql = pool.manage(mysql)
于 2008-09-19T01:38:19.027 回答
18

IMO,“更明显/更惯用/更好的解决方案”是使用现有的 ORM 而不是发明类似 DAO 的类。

在我看来,ORM 比“原始”SQL 连接更受欢迎。为什么?因为 Python面向对象的,从 SQL 行到对象的映射绝对必要的。处理不映射到 Python 对象的 SQL 行的用例并不多。

我认为SQLAlchemySQLObject(以及相关的连接池)是更惯用的 Pythonic 解决方案。

池作为一个单独的特性并不是很常见,因为纯 SQL(没有对象映射)对于受益于连接池的复杂、长时间运行的进程并不是很流行。是的,使用了纯 SQL ,但它总是用于更简单或更受控制的应用程序中,而池化没有帮助。

我想你可能有两种选择:

  1. 修改您的类以使用 SQLAlchemy 或 SQLObject。虽然这起初看起来很痛苦(所有工作都被浪费了),但您应该能够利用所有的设计和思想。这只是采用广泛使用的 ORM 和池化解决方案的练习。
  2. 使用您概述的算法推出您自己的简单连接池 - 您循环通过的简单连接集或列表。
于 2008-09-19T02:13:07.260 回答
9

旧线程,但对于通用池(连接或任何昂贵的对象),我使用类似的东西:

def pool(ctor, limit=None):
    local_pool = multiprocessing.Queue()
    n = multiprocesing.Value('i', 0)
    @contextlib.contextmanager
    def pooled(ctor=ctor, lpool=local_pool, n=n):
        # block iff at limit
        try: i = lpool.get(limit and n.value >= limit)
        except multiprocessing.queues.Empty:
            n.value += 1
            i = ctor()
        yield i
        lpool.put(i)
    return pooled

哪个是懒惰的构造,有一个可选的限制,并且应该推广到我能想到的任何用例。当然,这假设您确实需要任何资源的池化,而对于许多现代 SQL 类您可能不需要。用法:

# in main:
my_pool = pool(lambda: do_something())
# in thread:
with my_pool() as my_obj:
    my_obj.do_something()

这确实假设 ctor 创建的任何对象在需要时都具有适当的析构函数(某些服务器不会终止连接对象,除非它们被显式关闭)。

于 2014-07-14T16:53:14.827 回答
3

我一直在寻找同样的东西。

我找到了pysqlpool和sqlalchemy池模块

于 2009-05-14T17:41:51.780 回答
1

如果您的应用决定开始使用多线程,那么创建自己的连接池是一个坏主意。为多线程应用程序创建连接池比为单线程应用程序创建连接池要复杂得多。在这种情况下,您可以使用 PySQLPool 之类的东西。

如果您正在寻找性能,那么使用 ORM 也是一个坏主意。

如果您要处理必须同时处理大量选择、插入、更新和删除的大型/重型数据库,那么您将需要性能,这意味着您需要编写自定义 SQL 来优化查找和锁定时间。使用 ORM,您通常没有这种灵活性。

所以基本上,是的,您可以创建自己的连接池并使用 ORM,但前提是您确定不需要我刚才描述的任何内容。

于 2011-08-22T22:05:55.430 回答
1

回复一个旧线程但我上次检查时,MySQL 提供连接池作为其驱动程序的一部分。

您可以在以下位置查看它们:

https://dev.mysql.com/doc/connector-python/en/connector-python-connection-pooling.html

从 TFA,假设您要明确打开连接池(如 OP 所述):

dbconfig = {  "database": "test", "user":"joe" }
cnxpool = mysql.connector.pooling.MySQLConnectionPool(pool_name = "mypool",pool_size = 3, **dbconfig)

然后通过 get_connection() 函数从池中请求访问该池。

cnx1 = cnxpool.get_connection()
cnx2 = cnxpool.get_connection()
于 2017-06-10T17:32:34.367 回答
1

使用DBUtils,简单可靠。

pip install DBUtils
于 2018-11-11T07:05:22.527 回答