2

私はコードベース、特にデータベース接続部分を調べていたところ、この問題に遭遇しました。

まず、次の要素を使用してデータベースにカーソルを合わせます。

from django.db import connection, transaction
cursor = connection.cursor()

接続はモジュール属性であるため、スレッドモデルでは、すべてのスレッドがその変数を共有します。少し奇妙に聞こえます。さらに詳しく説明すると、cursor()メソッドはdjango.db.backends.BaseDatabaseWrapperに属しており、次のようになります。

def cursor(self):
        self.validate_thread_sharing()
        if (self.use_debug_cursor or
            (self.use_debug_cursor is None and settings.DEBUG)):
            cursor = self.make_debug_cursor(self._cursor())
        else:
            cursor = util.CursorWrapper(self._cursor(), self)
    return cursor

重要なのは_cursor()の呼び出しです。これは、使用されているデータベースのバックエンドコードを実行します。MySQLの場合、django.db.backends.mysql.DatabaseWrapperで_cursor()メソッドを実行します。これは次のようになります。

def _cursor(self):
    new_connection = False
    if not self._valid_connection():
        new_connection = True
        kwargs = {
            'conv': django_conversions,
            'charset': 'utf8',
            'use_unicode': True,
        }
        settings_dict = self.settings_dict
        if settings_dict['USER']:
            kwargs['user'] = settings_dict['USER']
        if settings_dict['NAME']:
            kwargs['db'] = settings_dict['NAME']
        if settings_dict['PASSWORD']:
            kwargs['passwd'] = settings_dict['PASSWORD']
        if settings_dict['HOST'].startswith('/'):
            kwargs['unix_socket'] = settings_dict['HOST']
        elif settings_dict['HOST']:
            kwargs['host'] = settings_dict['HOST']
        if settings_dict['PORT']:
            kwargs['port'] = int(settings_dict['PORT'])
        # We need the number of potentially affected rows after an
        # "UPDATE", not the number of changed rows.
        kwargs['client_flag'] = CLIENT.FOUND_ROWS
        kwargs.update(settings_dict['OPTIONS'])
        self.connection = Database.connect(**kwargs)
        self.connection.encoders[SafeUnicode] = self.connection.encoders[unicode]
        self.connection.encoders[SafeString] = self.connection.encoders[str]
        connection_created.send(sender=self.__class__, connection=self)
    cursor = self.connection.cursor()
    if new_connection:
        # SQL_AUTO_IS_NULL in MySQL controls whether an AUTO_INCREMENT column
        # on a recently-inserted row will return when the field is tested for
        # NULL.  Disabling this value brings this aspect of MySQL in line with
        # SQL standards.
        cursor.execute('SET SQL_AUTO_IS_NULL = 0')
    return CursorWrapper(cursor)

したがって、新しいカーソルが必ずしも作成されるとは限りません。_cursor()の呼び出しがすでに行われている場合は、以前に使用されたカーソルが返されます。

スレッドモデルでは、複数のスレッドが同じデータベースカーソルを共有している可能性があることを意味します。これは、ノーノーのように見えます。

Djangoではスレッド化が許可されていないことを示す他の兆候もあります。django / db / init .pyからのこのモジュールレベルのコード。たとえば、次のようになります。

def close_connection(**kwargs):
    for conn in connections.all():
        conn.close()
signals.request_finished.connect(close_connection)

したがって、要求が終了すると、すべてのデータベース接続が閉じられます。同時リクエストがある場合はどうなりますか?

多くのものが共有されているようです。これは、スレッドが許可されていないことを示しています。同期コードはどこにも見当たりませんでした。

ありがとう!

4

0 に答える 0