2012-05-17 55 views
4

我的django應用程序將django模型保存到遠程數據庫。有時節省是突然的。爲了將應用程序的主線程(* thread_A *)從保存多個對象到數據庫的時間間隔中解放出來,我考慮使用collections.deque將模型對象傳送到一個單獨的線程(* thread_B *)並且* thread_B *按順序保存它們。Python GIL:是django save()阻塞?

但我不確定這個計劃。 save()返回新數據庫條目的ID,所以它只有在數據庫響應後纔會「結束」,這是在事務結束時。

是否真的django.db.models.Model.save()阻止GIL -wise並在交易釋放其他的Python線程

+0

您是否打算在'save()'過程中從任何其他線程訪問數據庫? –

+0

@DonalFellows在我的具體情況 - 不是本地。一些遠程觀察者當然可以查詢數據庫,但這是正常的數據庫事務使用。 – Jonathan

+0

[David Beazley's 2011 Pycon GIL presentation](http://www.dabeaz.com/talks/EmbraceGIL/EmbracingGIL.pdf)看起來相關 – Jonathan

回答

7

Django的save()對GIL沒有任何特別之處。事實上,在Python代碼中幾乎沒有什麼可以用GIL來完成 - 當它被執行時,線程必須保存GIL。

只有兩種方式GIL可以在save()得到釋放:

  • Python的決定切換線程(後sys.getcheckinterval()指令)
  • Django的調用實現釋放GIL
  • 數據庫接口程序

第二點可能是您正在查找的內容 - 執行SQL COMMIT,並在執行期間,SQL後端釋放GIL。但是,這取決於SQL接口,我不確定流行的實際上是否釋放了GIL *。

此外,save()做了很多不僅僅是運行幾個UPDATE/INSERT陳述和COMMIT;它在Python中做了很多簿記,它必須持有GIL。總之,我不確定你會從save()到另一個線程獲得什麼。


UPDATE:從尋找來源,我瞭解到,無論是sqlite模塊和psycopg做釋放GIL時,他們呼籲數據庫例程,我想其他的接口做同樣的。

+0

不要I/O調用釋放GIL嗎?它真的需要明確嗎? – ubik

+1

是的,它的確如此。用C編寫的例程不會自動釋放GIL,但作者明確必須這樣做。請參閱http://docs.python.org/c-api/init.html?highlight=gil#releasing-the-gil-from-extension-code –

+0

好的,我假設SQL接口是用Python編寫的。 – ubik

-4

我認爲python不會自己鎖定任何東西,但數據庫呢。

+2

你知道GIL是什麼嗎? http://en.wikipedia.org/wiki/Global_Interpreter_Lock – NPE

+0

數據庫是遠程因此通過IP連接,因此我不知道你的意思,它不能阻止連接,問題是本地發生了什麼 – Jonathan

+0

是的,我知道什麼是GIL,但Django不使用線程,我認爲它不使用GIL。 – Denis

2

通常,您不應該擔心Django應用程序中的線程。如果您使用Apache,gunicorn或幾乎任何其他服務器爲開發服務器提供服務,服務器將產生多個進程並完全逃避GIL。例外情況是,如果您使用gevent來使用gunicorn,在這種情況下會有多個進程,但在這些進程中也會有微線程 - 在這種情況下,併發性會有所幫助,但您不必自己管理線程以利用那個。唯一需要擔心GIL的情況是,如果您嘗試產生多個線程來處理單個請求,這通常不是一個好主意。 Django save()方法不會釋放GIL本身,但數據庫後端將(在大多數情況下save()中花費的大部分時間將執行數據庫I/O)。但是,在設計良好的Web應用程序中正確利用這一點幾乎是不可能的。即使在同步完成後,您的觀點應該會很快 - 如果他們做了太多的工作以便快速完成工作,那麼請與Celery或其他任務管理員一起延期完成額外工作。如果您嘗試在視圖中進行線索處理,則必須在向客戶端發送響應之前完成該線程,而在大多數情況下,這對客戶端無任何幫助,只會增加額外開銷。

+0

我的系統不是一個Web應用程序。我使用django純粹是爲了ORM,沒有涉及網絡服務器 – Jonathan

+0

嗯,我明白了。那麼,如果你在python中進行了很多處理(在數據庫訪問之外的CPU時間),那麼你可以使用多處理庫或者啓動多個進程,這就是我使用Django進行ORM的腳本(我的即使使用多個進程也需要花費數天時間)。但是如果你使用線程,他們至少可以在數據庫I/O操作上覆用,因爲實際的阻塞I/O將釋放GIL。 –