有时,我会使用 connection.cursor()
执行原始查询。而不是使用 ORM(因为它绝对不是 Elixir )。
我注意到,在我完成数据库后,在几个地方我没有调用显式 cursor.close()
。到目前为止,这还没有导致任何错误或性能问题。我想知道如果不显式关闭光标,我可能会遇到什么样的问题,会出现什么问题?
据我了解,Django 中的 connection
和 cursor
遵循“Python Database API Specification v2.0”(PEP-249)。而且,根据它,每当调用 __del__()
方法时,cursor
都会自动关闭。我想问题也可能是:是否有不调用的用例?
仅供引用,我使用的是 Python 2.7 和 Django 1.6.5。
最佳答案
Django 的 cursor
类只是底层 DB 的 cursor
的包装器,因此保持 cursor
打开的效果基本上与底层数据库驱动程序。
根据 psycopg2(psycopg2 是 Django 用于 PostgreSQL 数据库的数据库驱动程序)FAQ ,它们的游标是轻量级的,但会缓存您使用游标对象进行的查询返回的数据,这可能会浪费内存:
Cursors are lightweight objects and creating lots of them should not pose any kind of problem. But note that cursors used to fetch result sets will cache the data and use memory in proportion to the result set size. Our suggestion is to almost always create a new cursor and dispose old ones as soon as the data is not required anymore (call close() on them.) The only exception are tight loops where one usually use the same cursor for a whole bunch of INSERTs or UPDATEs.
Django 使用 MySQLdb
作为 MySQL 的后端,它有几种不同类型的游标,包括一些实际上将其结果集存储在服务器端的游标。 MySQLdb
documentation for Cursor.close
需要注意的是,在您完成后关闭服务器端光标非常重要:
If you are using server-side cursors, it is very important to close the cursor when you are done with it and before creating a new one.
然而,这与 Django 无关,因为它使用 MySQLdb
提供的默认 Cursor
类,它将结果存储在客户端。让使用过的游标处于打开状态只会有浪费存储结果集使用的内存的风险,就像 psycopg2
一样。 close
method游标上只是删除对数据库连接的内部引用并耗尽存储的结果集:
def close(self):
"""Close the cursor. No further queries will be possible."""
if not self.connection: return
while self.nextset(): pass
self.connection = None
据我所知,Django 使用的所有剩余后端( cx_oracle 、 sqlite3/pysqlite2 )都遵循相同的模式;通过删除/重置存储的结果/对象引用来释放内存。 sqlite3 docs更别提 Cursor
类有 close 方法了,它只是在包含的示例代码中偶尔使用。
你是对的,当 __del__()
在 cursor
对象上被调用时 cursor
将被关闭,因此需要显式关闭仅当您保持对 cursor
的长期引用时才会出现问题;例如self.cursor
对象,您将其保留为类的实例方法。
关于python - 显式 cursor.close() 的必要性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24661754/