bigywater.tech
Django · 42

数据库连接生命周期

Django 什么时候连数据库?什么时候断?多线程时连接是共享的吗?这篇在真实的 gunicorn 下,用 PostgreSQL 的 pg_backend_pid() 和 pg_stat_activity 直接观察。

惰性
第一次查询才建立连接;没有查询的请求里 connection.connection 是 None
每请求一个
默认 CONN_MAX_AGE=0:6 个连续请求 6 个不同的 pg_backend_pid,请求结束连接关闭
线程局部
4 个处理线程 → 4 个数据库连接,互不共享

默认:每个请求一个连接

实测 · 本机执行输出
  还没有任何查询时,connection.connection 是否已建立: False
  每个请求里 pg_backend_pid(): [9031, 9032, 9033, 9034, 9035, 9036]
  每个请求开始时 connection.connection 是 None 吗: [True, True, True, True, True, True]
  请求处理线程: ['MainThread']
  请求结束后数据库端还剩多少个来自应用的连接: 0 (请求结束时连接被关闭)

用 pg_backend_pid() 看数据库端处理这条连接的后端进程:每个请求都不一样,说明每次都是新连接。请求结束时连接被关闭,数据库端只剩 0 个。

线程局部的连接

实测 · 本机执行输出
  40 个请求用到的不同数据库连接(pid)数: 4 ;不同处理线程数: 4
  请求全部结束后,数据库端仍保持的连接数: 4 (持久连接没有被关闭)
  服务停止后数据库端连接数: 0

connection 是 connections[DEFAULT_DB_ALIAS] 的代理,内部是线程局部存储。所以「连接数 = 处理线程数(× worker 数)」——线程池的大小直接决定持久连接的上限(第 43 篇看到它的后果)。

分步演示:连接的一生

数据库连接生命周期
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7 / Django 6.1.1(默认用 SQLite,其它数据库会在文中注明),用 django.test.Client 或真实的本机服务器进程实测;计时用 time.perf_counter,数字每次运行会有小幅抖动。gunicorn 26.2 1 worker × 1 线程 / 4 线程;PostgreSQL 16.15(本机临时实例,端口 9411);连接数用 pg_stat_activity 统计
    • 没有验证:ASGI(uvicorn)下的连接模型、异步视图里的连接、多数据库别名、connection.close() / close_if_unusable_or_obsolete 的细节、请求外(管理命令、Celery)的连接生命周期
    京ICP备2026067502号-1京公网安备11010502063487号