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

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

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

该进程运行时间较长,并且有许多线程需要发出请求,但并非所有线程同时发出......具体来说,他们在短暂地写出大部分结果之前做了相当多的工作。

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

有帮助吗?

解决方案

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

在我看来,ORM 比“原始”SQL 连接更流行。为什么?因为Python OO,以及从 SQL 行到对象的映射 绝对必要。处理不映射到 Python 对象的 SQL 行的情况并不多。

我觉得 SQL炼金术 或者 SQL对象 (以及相关的连接池)更惯用的 Pythonic 解决方案。

池作为一个单独的功能并不常见,因为纯 SQL(没有对象映射)对于受益于连接池的复杂、长时间运行的进程来说并不是很受欢迎。是的,纯 SQL 使用,但它总是用于更简单或更受控制的应用程序,在这些应用程序中池没有帮助。

我想你可能有两种选择:

  1. 修改您的类以使用 SQLAlchemy 或 SQLObject。虽然一开始这看起来很痛苦 [所有工作都被浪费了],但您应该能够利用所有的设计和思想,这只是采用广泛使用的 ORM 和池解决方案的一个练习。
  2. 使用您概述的算法滚动您自己的简单连接池 - 您循环使用的简单连接集或列表。

其他提示

在MySQL 中?

我想说不要担心连接池。它们通常是麻烦的根源,并且对于 MySQL,它们不会为您带来您所希望的性能优势。从政治上讲,走这条路可能需要付出很大的努力,因为在这个领域有太多关于连接池优点的最佳实践和教科书的废话。

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

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

只要不存在需要克服的政治障碍,如果不这样做,您可能会受益匪浅。

包装您的连接类。

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

更新:我在 dbpool.py 中添加了这样的内容:

import sqlalchemy.pool as pool
import MySQLdb as mysql
mysql = pool.manage(mysql)

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

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()

这确实假设无论需要什么对象构造函数都具有适当的析构函数(某些服务器不会终止连接对象,除非它们被显式关闭)。

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

我发现了 pysql池sqlalchemy 池模块

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

如果您追求性能,那么使用 ORM 也是一个坏主意。

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

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

回复一个旧线程,但我上次检查时,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()

使用 DBUtils, ,简单可靠。

pip install DBUtils
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top