2016-04-17 7 views
0

django db接続スレッドセーフに関する多くの質問がありますが、それらはすべてデフォルトの要求スレッドを尋ねているようです。カスタムスレッドスクリプトでのDjango DB接続の使用

私は何のスレッドでデータベース接続使用するカスタムスクリプト書いていた場合:

from django.db import connections 
import threading 

class Transform(object): 
    def transform_data(self, listing): 
     cursor = self.connection.cursor() 
     cursor.execute('SELECT ... WHERE id = %s', listing.id) 
     data = cursor.fetchall() 
     ... 

    def run(self): 
     connection = self.connections['legacy'] 
     for listing in listings: 
      threading.Thread(target=self.transform_data, args=[listing]) 

どのように安全な結果の面でtransform_dataスレッド内のデータは、カーソルから他のスレッドと混同されていないですか?

答えて

0

を使用しているかデータベースに非常に依存している共有している場合。デフォルトでは、これらの接続はスレッド間で共有できません。そうしようとするとDatabaseErrorになります。

常にconnections[alias]の中で、のクエリを実行するスレッドを使用してください。親スレッドのconnections[alias]にアクセスして、オブジェクトを子スレッドに渡してはいけません。これにより、使用するすべての接続オブジェクトが現在のスレッドに対してローカルであることが保証され、スレッドに関する問題が回避されます。

あなたはこのようにそれを変更します、あなたのコードを修正し、それがスレッドセーフにするには:

from django.db import connections 
import threading 

class Transform(object): 
    def transform_data(self, listing): 
     # Access the database connection on the global `connections` object 
     # from within the child thread. 
     cursor = connections['legacy'].cursor() 
     cursor.execute('SELECT ... WHERE id = %s', listing.id) 
     data = cursor.fetchall() 
     ... 

    def run(self): 
     for listing in listings: 
      threading.Thread(target=self.transform_data, args=[listing]) 
1

理想的には、各スレッドは独自の接続を使用する必要があります。 transform_dataの中でselectクエリを実行すると、その時点でのデータのスナップショットが本質的に取得されます。他のスレッドが独自の接続を持っていれば、他のスレッドによって更新または削除されることを心配することなく行を取り出すことができます。

すべてのスレッドが正確に何が起こるか、同じ接続を使用して、トランザクション分離レベルにconnectionsオブジェクト内の各項目は、そのデータベースにスレッドローカル接続を返します