我正在查看代码库,特别是数据库连接部分,并且遇到了这个问题。
首先,使用以下stamentent获取光标到数据库:
from django.db import connection, transaction
cursor = connection.cursor()
connection是一个模块属性,因此在线程模型中,所有线程都将共享该变量。听起来有点奇怪。进一步潜水,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)
因此,如果任何请求完成,则关闭所有数据库连接。如果有并发请求怎么办?
似乎正在共享许多内容,这表明不允许进行线程化。我没有在任何地方看到同步代码。
谢谢!