打开和关闭游标和连接的建议做法
Posted
技术标签:
【中文标题】打开和关闭游标和连接的建议做法【英文标题】:Suggested practice for opening and closing cursors and connections 【发布时间】:2012-06-09 20:56:09 【问题描述】:以下是我的代码中的常见模式,我想了解更多关于游标和连接的内部结构。
cursor = connection.cursor()
cursor.execute("SET NAMES utf8")
cursor.execute(sql, args)
results = cursor.fetchall()
cursor.close()
到数据库的连接和游标之间有什么区别?开放连接是否有任何缺点(例如,几分钟?)。有未关闭的游标怎么办,有什么影响?连续执行多条SQL语句时,每次都要新建一个游标吗?
【问题讨论】:
如果要重新使用光标,我通常会将其保持打开状态。这是数据库上的非活动会话,只要没有太多的游标处于打开状态,那么对服务器没有影响,并且您不会因不断打开和关闭以及再次重新打开等而产生开销。跨度> 【参考方案1】:这取决于底层实现——Cursor 对象在驱动程序中的实际含义。
在许多 DB-api 实现中,Cursor 对象并不“有趣”(即您可以保留很多对象并让 GC 担心它们),尤其是在您没有执行返回结果集的查询时。
我没有将 Python 与 Oracle 一起使用,但我怀疑(基于 JDBC 和其他方面的经验)Oracle 并非如此。 Oracle JDBC 驱动程序具有服务器端游标,快速关闭非常重要(每个连接的默认游标限制相当低;超过限制会导致尝试打开另一个游标失败)。
在 Oracle 中,依靠 GC 关闭游标可能会很危险,例如,如果您在循环中打开一个新游标,而 GC 会保留所有游标,直到循环函数返回。
如果这是真的,那么使用 with 语句构造来确保游标及时关闭可能会有所帮助,即使发生异常也是如此。
更新:您可以使用 contextlib.closure 作为上下文管理器,例如
with contextlib.closing(myconnection.cursor()) as curs:
curs.execute(...
# even if exception happens, cursor is still closed immediately
# after this block
【讨论】:
【参考方案2】:Cursor 类似于 python 中的迭代器。它使您能够遍历结果集,而无需将其全部保存在内存中。对于您正在使用的每个 RDBMS,可以以不同的方式实现光标。
如果垃圾收集器不删除未关闭的游标,它会占用一些内存。
您可以在一个连接中打开多个光标。
您可以保持连接打开。根据您使用的数据库,打开连接将使用一些资源,并且一次可以打开多少个连接。
【讨论】:
错了;游标与迭代器不同,游标是驱动程序制造的任何东西。至少在 mysql 中,整个结果集通常都在内存中。以上是关于打开和关闭游标和连接的建议做法的主要内容,如果未能解决你的问题,请参考以下文章
Java 技术篇 - 连接oracle数据库执行sql使用close()关闭createStatement()无效无法清除游标缓存问题解决,报“ORA-01000: 超出打开游标的最大数“错误解决方法