django数据库优化(一)

django数据库优化(一)

# 版本背景
python:3.7
django:2.2
mysql:8.0

前景:因为django在每次查询时就进行一次数据库连接操作,而且查询完成之后就立马关闭连接,因此在进行频繁操作数据库的场景下该操作十分不友好,会大大增加了数据库的压力,降低服务性能。
解决方案:修改django数据库的短连接,改用长连接

查阅官方文档:Django Databases

持久化连接

持久化连接避免了在每个请求中重新建立到数据库的连接的开销。它们由CONN_MAX_AGE定义连接最长生命周期的参数控制 。可以为每个数据库独立设置。

默认值为0,保留每次请求结束时关闭数据库连接的历史行为。要启用持久化连接,请将CONN_MAX_AGE设置为正值的秒数。对于无限制的持久化连接,请将其设置为None.

连接管理

Django 在第一次进行数据库查询时会打开一个到数据库的连接。它保持此连接打开并在后续请求中重用它。一旦连接超过定义的最大数值CONN_MAX_AGE或不再可用时,Django 将关闭连接 。

详细地说,Django 会在需要连接但还没有连接时自动打开一个数据库的连接——要么因为这是第一个连接,要么因为前一个连接已关闭。

在每个请求开始时,如果连接已达到最大值,Django 会关闭连接。如果您的数据库在一段时间后终止空闲连接,您应该设置CONN_MAX_AGE一个较低的值,以便 Django 不会尝试使用已被数据库服务器终止的连接。(这个问题可能只会影响非常低流量的网站。)

在每个请求结束时,如果连接已达到最大值或处于不可恢复的错误状态,Django 将关闭连接。如果在处理请求时发生任何数据库错误,Django 会检查连接是否仍然有效,如果无效则关闭它。因此,数据库错误最多影响一个请求;如果连接变得不可用,下一个请求将获得一个新的连接。

注意事项

由于每个线程都维护自己的连接,因此您的数据库必须至少支持与工作线程一样多的同时连接。

有时数据库不会被大多数视图访问,例如因为它是外部系统的数据库,或者由于缓存。在这种情况下,您应该设置CONN_MAX_AGE一个较低的值甚至 0,因为维护不太可能被重用的连接是没有意义的。这将有助于保持与该数据库的同时连接数较少。

开发服务器为它处理的每个请求创建一个新线程,消除持久连接的影响。不要在开发过程中启用它们。

当 Django 与数据库建立连接时,它会根据所使用的后端设置适当的参数。如果启用持久连接,则不再在每个请求中重复此设置。如果修改连接的隔离级别或时区等参数,则应该在每个请求结束时恢复 Django 的默认值,在每个请求开始时强制使用适当的值,或者禁用持久连接。

django使用长连接

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'xxxx',
        'USER': 'root',
        'PASSWORD': 'xxxx',
        'HOST': "xxxx",
        'PORT': '3306',
        'CHARSET': 'utf8mb4',
        'CONN_MAX_AGE': 8 * 3600,
    }
}

注意:在设置CONN_MAX_AGENone时,实际情况由于数据库本身的连接超时时间限制导致无法达到无限制的持久化连接。(Mysql的最大连接时间为8h。)

django数据库相关源码解析

相关源码位置:/site-packages/django/db/__ init __.py

# 对象
connections = ConnectionHandler()
connection = DefaultConnectionProxy()

# Register an event to reset saved queries when a Django request is started.
# 重置查询记录缓存
def reset_queries(**kwargs):
    for conn in connections.all():
        conn.queries_log.clear()


# Register an event to reset transaction state and close connections past
# their lifetime.
# 关闭不可用或超时(如果有设置 CONN_MAX_AGE)连接
def close_old_connections(**kwargs):
    for conn in connections.all():
        conn.close_if_unusable_or_obsolete()


# 信号机制Signals
# 在请求开始或完成时自动调用相应处理函数
signals.request_started.connect(reset_queries)
signals.request_started.connect(close_old_connections)
signals.request_finished.connect(close_old_connections)

django内部短连接的机制在于每次请求结束后触发信号量request_finished

signals.request_finished.connect(close_old_connections)

close_old_connections函数中调用了close_if_unusable_or_obsolete函数

def close_if_unusable_or_obsolete(self):
    """
    Close the current connection if unrecoverable errors have occurred
    or if it outlived its maximum age.
    """
    if self.connection is not None:
        # If the application didn't restore the original autocommit setting,
        # don't take chances, drop the connection.
        if self.get_autocommit() != self.settings_dict['AUTOCOMMIT']:
            self.close()
            return

        # If an exception other than DataError or IntegrityError occurred
        # since the last commit / rollback, check if the connection works.
        if self.errors_occurred:
            if self.is_usable():
                self.errors_occurred = False
            else:
                self.close()
                return

        if self.close_at is not None and time.time() >= self.close_at:
            self.close()
            return

当参数CONN_MAX_AGE设置为默认值0时,执行了上文下列代码

if self.close_at is not None and time.time() >= self.close_at:
    self.close()
    return

从而导致django每次请求开始建立数据库连接,操作完成后立刻关闭数据库连接操作。

你可能感兴趣的:(django,mysql,python,django)