我已经开发了一些类似于DAO的自定义类来满足我的项目的一些非常专业的需求,这是一个服务器端进程,它不在任何类型的框架内运行.
解决方案很有效,除了每次发出新请求时,我都会通过MySQLdb.connect打开一个新连接.
什么是最好的"drop in"解决方案,将其转换为在python中使用连接池?我正在想象类似于Java的公共DBCP解决方案.
这个过程是长时间运行的,并且有很多线程需要发出请求,但不是所有的同时...特别是他们在写出一大块结果的短暂爆发之前做了很多工作.
编辑添加:经过一些搜索,我发现anitpool.py看起来不错,但由于我对python相对较新,我想我只是想确保我没有错过更明显/更惯用/更好的解决方案.
在MySQL?
我想说不要打扰连接池.它们通常是麻烦的源头,而MySQL则不会为您带来您希望的性能优势.这条道路可能需要付出很多努力 - 政治上 - 因为在这个空间里有很多关于连接池优势的最佳实践手动和教科书措辞.
连接池只是无状态应用程序(例如HTTP协议)的后Web时代与有状态长期批处理应用程序的前Web时代之间的桥梁.由于连接在预网络数据库中非常昂贵(因为没有人过多地关心建立连接需要多长时间),后网应用程序设计了这种连接池方案,因此每次访问都不会产生这种巨大的处理开销在RDBMS上.
由于MySQL更像是一个网络时代的RDBMS,因此连接非常轻巧和快速.我编写了许多高容量的Web应用程序,它们根本不使用连接池来处理MySQL.
只要不存在需要克服的政治障碍,这可能会使您从中受益.
包装你的连接类.
设置您建立的连接数限制.返回未使用的连接.拦截接近释放连接.
更新:我在dbpool.py中添加了这样的内容:
import sqlalchemy.pool as pool import MySQLdb as mysql mysql = pool.manage(mysql)
IMO,"更明显/更惯用/更好的解决方案"是使用现有的ORM而不是发明类似DAO的类.
在我看来,ORM比"原始"SQL连接更受欢迎.为什么?因为Python 是 OO,从SQL行到对象的映射是绝对必要的.处理不映射到Python对象的SQL行的情况并不多.
我认为SQLAlchemy或SQLObject(以及相关的连接池)是更惯用的Pythonic解决方案.
池作为单独的功能并不常见,因为纯SQL(没有对象映射)对于受益于连接池的复杂,长时间运行的流程并不是非常流行.是的,纯粹的SQL 被使用,但它总是在池是没有帮助的简单或多个控制应用中使用.
我想你可能有两种选择:
修改您的类以使用SQLAlchemy或SQLObject.虽然这一开始显得很痛苦[所有浪费的工作],但您应该能够利用所有的设计和思想,而这只是采用广泛使用的ORM和汇集解决方案的练习.
使用您概述的算法滚动您自己的简单连接池 - 您循环的简单Set或List连接.
旧线程,但对于通用池(连接或任何昂贵的对象),我使用类似的东西:
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创建的任何对象在需要时都有适当的析构函数(某些服务器不会终止连接对象,除非它们被显式关闭).