我已经开发了一些类似于DAO的自定义类来满足我的项目的一些非常专业的需求,这是一个不在任何框架内运行的服务器端进程。
解决方案很有效,除了每次发出新请求时,我都会通过MySQLdb.connect打开一个新连接。
将此切换为在python中使用连接池的最佳“drop in”解决方案是什么?我正在想象类似于Java的公共DBCP解决方案。
这个过程是长时间运行的,并且有许多线程需要发出请求,但不是所有线程都要同时...具体来说,他们在写出一大块结果的短暂爆发之前做了很多工作。
编辑添加: 经过一番搜索,我发现anitpool.py看起来不错,但由于我对python比较陌生,我想我只是想确保我没有错过更明显/更惯用/更好的解决方案。
答案 0 :(得分:22)
在MySQL?
我说不要打扰连接池。它们通常是麻烦的源头,而MySQL则不会为您带来您希望的性能优势。这条道路可能需要付出很多努力 - 政治上 - 因为在这个空间里有很多关于连接池优势的最佳实践手动和教科书措辞。
连接池只是无状态应用程序(例如HTTP协议)的后网时代与有状态长期批处理应用程序的前网时代之间的桥梁。由于连接在预网络数据库中非常昂贵(因为没有人过多地关心建立连接需要多长时间),后网应用程序设计了这种连接池方案,因此每次访问都不会产生这种巨大的处理开销在RDBMS上。
由于MySQL更像是一个网络时代的RDBMS,因此连接非常轻巧和快速。我编写了许多高容量的Web应用程序,它们根本不使用连接池。
只要不存在需要克服的政治障碍,这可能会使您从中受益,并且可以从中受益。
答案 1 :(得分:16)
包装您的连接类。
设置您建立的连接数限制。 返回未使用的连接。 拦截接近释放连接。
更新: 我把这样的东西放在dbpool.py中:
import sqlalchemy.pool as pool
import MySQLdb as mysql
mysql = pool.manage(mysql)
答案 2 :(得分:16)
IMO,“更明显/更惯用/更好的解决方案”是使用现有的ORM,而不是发明类似DAO的类。
在我看来,ORM比“原始”SQL连接更受欢迎。为什么?因为Python 是 OO,并且从SQL行到对象的映射是绝对必要。处理不映射到Python对象的SQL行的情况并不多。
我认为SQLAlchemy或SQLObject(以及相关的连接池)是更惯用的Pythonic解决方案。
将池作为单独的功能并不常见,因为纯SQL(没有对象映射)对于受益于连接池的复杂,长时间运行的流程并不是非常流行。是的,纯SQL 是使用的,但它总是用于更简单或更受控制的应用程序,其中池没有帮助。
我认为你可能有两种选择:
答案 3 :(得分:6)
旧线程,但对于通用池(连接或任何昂贵的对象),我使用类似的东西:
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创建的任何对象在需要时都有适当的析构函数(某些服务器不会终止连接对象,除非它们被明确关闭)。
答案 4 :(得分:2)
我一直在寻找同样的东西。
答案 5 :(得分:2)
如果您的应用决定开始使用多线程,那么建立自己的连接池是一个不错的主意。为多线程应用程序创建连接池要比单线程应用程序更复杂。在这种情况下,您可以使用类似PySQLPool的东西。
如果您正在寻找性能,那么使用ORM也是一个不错的主意。
如果你要处理那些必须处理大量选择,插入的庞大/繁重的数据库, 同时更新和删除,然后您将需要性能,这意味着您将需要编写自定义SQL来优化查找和锁定时间。使用ORM,您通常不具备这种灵活性。
所以基本上,是的,你可以建立自己的连接池并使用ORM,但前提是你确定你不需要我刚才所描述的任何内容。
答案 6 :(得分: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()
答案 7 :(得分:0)
使用DBUtils,简单可靠。
pip install DBUtils