2012-06-05 41 views
1

以下是我在代碼中使用的常見模式,我更想知道遊標和連接的內部。關於打開和關閉遊標和連接的建議練習

cursor = connection.cursor() 
cursor.execute("SET NAMES utf8") 
cursor.execute(sql, args) 
results = cursor.fetchall() 
cursor.close() 

與數據庫的連接和遊標的區別是什麼?開放連接有什麼不利之處(例如,幾分鐘?)。怎麼樣有未關閉的遊標,有什麼影響?當連續執行多個SQL語句時,是否應該每次創建一個新的遊標?

+0

哪種語言是這樣一個背景下,經理這樣? – Sebas

+0

@Sebas python ......... – David542

+0

如果遊標將被重新使用,我通常會將其打開。這是一個不活躍的數據庫會話,只要沒有太多的遊標保持打開狀態,那麼就不會對服務器產生影響,並且不會導致連續打開和關閉以及重新打開等。 – Ben

回答

1

光標與Python中的迭代器類似。它使您能夠遍歷結果集,而無需將其保存在內存中。對於您正在使用的每個RDBMS,遊標可以以不同的方式實現。

如果垃圾收集器不刪除它,未封閉的遊標將使用一些內存。

您可以在一個連接中打開多個遊標。

您可以保持連接打開。根據您使用的數據庫,打開的連接將使用一些資源,並且一次可以打開多少個連接的限制。

+0

錯誤;遊標不是類似於迭代器的東西,遊標是驅動程序所做的任何事情。至少在MySQL中,無論如何,整個結果集通常都在內存中。 – MarkR

3

它取決於底層實現 - Cursor對象實際上是在驅動程序內部。在許多DB-api實現中,Cursor對象不是「有趣的」(即,你可以保留它們很多,讓GC擔心它們),特別是如果你還沒有完成返回結果集的查詢。

我還沒有和Oracle一起使用過Python,但我懷疑(根據JDBC和其他人的經驗),在Oracle中並非如此。 Oracle JDBC驅動程序具有服務器端遊標,關鍵是快速關閉(默認每連接遊標限制相當低;超出限制會導致嘗試打開另一個遊標時失敗)非常重要。

在Oracle中,如果您在循環中打開一個新的遊標並且GC保留它們直到循環函數返回,那麼依靠GC關閉遊標可能是危險的。

如果這是真的,那麼即使發生異常,使用with-statement構造來確保及時關閉遊標可能會有所幫助。


更新:您可以使用contextlib.closing作爲作爲

with contextlib.closing(myconnection.cursor()) as curs: 
    curs.execute(... 
    # even if exception happens, cursor is still closed immediately 
    # after this block 
+0

你有沒有機會檢查它是否適用於MySQLDB? –