ale*_*cxe 33 python database django database-connection cursor
我不时connection.cursor()使用ORM而不是使用ORM来执行原始查询(因为它绝对不是银弹).
我注意到在cursor.close()我完成数据库之后,我在几个地方都没有打电话给我.到目前为止,这不会导致任何错误或性能问题.我想知道如果没有明确地关闭光标我可能会遇到什么样的问题,哪些可能出错?
据我了解,connection并cursor在Django遵循"Python数据库API规范v2.0"(PEP-249).并且,根据它,cursor只要__del__()调用方法,它就会自动关闭.我想这个问题也可能是:在没有被调用时是否存在用例?
仅供参考,我使用的是Python 2.7和Django 1.6.5.
dan*_*ano 19
Django的cursor类只是底层数据库的包装器cursor,因此保持cursor打开状态的效果基本上与底层数据库驱动程序有关.
根据psycopg2(psycopg2是Django用于PostgreSQL DB的DB驱动程序)常见问题解答,它们的游标是轻量级的,但会缓存从使用游标对象进行的查询返回的数据,这可能会浪费内存:
游标是轻量级对象,创建大量游标不应该造成任何问题.但请注意,用于获取结果集的游标将缓存数据并使用与结果集大小成比例的内存.我们的建议是几乎总是创建一个新的游标并在不再需要数据时立即处理旧游标(对它们调用close().)唯一的例外是紧密循环,其中一个通常使用相同的游标来获取一大堆INSERT或UPDATE.
Django MySQLdb用作MySQL的后端,它有几种不同类型的游标,包括一些实际在服务器端存储结果集的游标.在MySQLdb对文件Cursor.close做出一点要注意,它关闭是非常重要的服务器端游标时,你与他们做的:
如果您使用的是服务器端游标,则在完成游标并创建新游标之前关闭游标非常重要.
但是,这与Django无关,因为它使用了Cursor提供的默认类MySQLdb,它在客户端存储结果.将使用过的游标保持打开只会冒着浪费存储结果集使用的内存的风险,就像这样psycopg2.的close方法上的光标只删除内部参考分贝连接和排出所存储的结果集:
def close(self):
"""Close the cursor. No further queries will be possible."""
if not self.connection: return
while self.nextset(): pass
self.connection = None
Run Code Online (Sandbox Code Playgroud)
尽管我从查看源代码可以看出,Django使用的所有剩余后端(cx_oracle,sqlite3/pysqlite2)都遵循相同的模式; 通过删除/重置存储的结果/对象引用来释放内存.在sqlite3的文档甚至没有提到的是,Cursor类有密切的方法,而且只有在所包含的示例代码使用断断续续.
你是对的,cursor当对象__del__()被调用时,它将被关闭cursor,所以如果你保持长期参考,那么明确关闭的需要只是一个问题cursor.例如self.cursor,您作为类的实例方法保留的对象.
__del__/ .close():
__del__ 不保证被称为__del__(不好的做法,但是都是)一般在服务器连接上
大多数服务器都有空闲超时配置属性(让我们称之为T).如果连接空闲超过T秒,服务器将删除该连接.大多数服务器还具有用于设置工作线程池(W)大小的属性.如果您已经与服务器建立了W连接,则在尝试新连接时可能会挂起.第二个想象,您没有明确关闭连接的选项.在这种情况下,您必须将超时设置得足够小,以至于您的工作池永远不会被完全使用,这是您拥有多少并发连接的函数.
但是,如果你关闭你的游标/连接(即使上面的[3]不相同,它们的行为方式类似),那么你不必管理这些服务器配置属性,你的线程池只需要很大足以管理所有并发连接(偶尔等待新资源的选项).我已经看到一些服务器(例如Cassandra上的Titan)无法从线程池中的工作负载中恢复,因此整个服务器都会关闭直到重新启动.
TL/DR
如果您使用非常完善的库,就像dano提到的那样,您将不会遇到问题.如果您使用较少的原始库,如果您不打电话.close(),最终可能会在服务器上阻止获取工作线程,具体取决于您的服务器配置和访问速率.