python - 显式 cursor.close() 的必要性

标签 python django database-connection database-cursor

有时,我会使用 connection.cursor() 执行原始查询。而不是使用 ORM(因为它绝对不是 Elixir )。

我注意到,在我完成数据库后,在几个地方我没有调用显式 cursor.close()。到目前为止,这还没有导致任何错误或性能问题。我想知道如果不显式关闭光标,我可能会遇到什么样的问题,会出现什么问题?

据我了解,Django 中的 connectioncursor 遵循“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_oraclesqlite3/pysqlite2 )都遵循相同的模式;通过删除/重置存储的结果/对象引用来释放内存。 sqlite3 docs更别提 Cursor close 方法了,它只是在包含的示例代码中偶尔使用。

你是对的,当 __del__()cursor 对象上被调用时 cursor 将被关闭,因此需要显式关闭仅当您保持对 cursor 的长期引用时才会出现问题;例如self.cursor 对象,您将其保留为类的实例方法。

关于python - 显式 cursor.close() 的必要性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24661754/

相关文章:

java - jboss wildfly 数据源连接失败 - 在配置的阻塞超时内没有可用的托管连接

python - 使用python解析XBRL

python - MySQL INSERT ... ON DUPLICATE KEY UPDATE with django 1.4 for bulk insert

django - Django 的迁移是什么?

Django 。如何获取GenericForeignKey对应的对象

java - 无法使用 JDBC 连接到 MySQL 数据库

java - 数据库连接池(w/Java)

python - matplotlib:绘图时忽略异常值

javascript - 用于网页抓取的 Selenium 与 BeautifulSoup

python - 如何一次性抓取超过 100 个谷歌页面