25-数据库连接池-Django连接复用与连接数上限控制

文章目录

  • 数据库连接池到底解决什么问题------不是让连接更快,而是让连接活着
    • 导入语
    • [1 ~> 没有连接池时------每个请求都"租房",而不是"住酒店"](#1 ~> 没有连接池时——每个请求都"租房",而不是"住酒店")
      • [1.1 MySQL 连接的生命周期](#1.1 MySQL 连接的生命周期)
    • [2 ~> Django 默认的连接行为](#2 ~> Django 默认的连接行为)
    • [3 ~> `django-db-connection-pool`------给 Django 加上连接池](#3 ~> django-db-connection-pool——给 Django 加上连接池)
      • [3.1 安装配置](#3.1 安装配置)
      • [3.2 效果](#3.2 效果)
    • [4 ~> Java 的 HikariCP 和 Django 连接池的对比](#4 ~> Java 的 HikariCP 和 Django 连接池的对比)
    • [5 ~> 连接池的常见误区](#5 ~> 连接池的常见误区)
    • [思考 && 总结](#思考 && 总结)
    • 结尾

数据库连接池到底解决什么问题------不是让连接更快,而是让连接活着

📖 文章简介: "数据库连接池就是让连接更快"------这句话只对了一半。连接池的核心价值不是速度,而是连接复用 。没了连接池,每个请求都要经过 TCP 三次握手 → MySQL 认证 → 执行 SQL → 四次挥手------整个过程开销可达几十毫秒。连接池把这个过程压缩为"从池子里借一个已有的连接 → 用完还回去"。本文从 MySQL 连接的生命周期讲起,分析 Django 默认连接行为的问题(每个线程一个连接,线程多了连接数膨胀),并介绍 django-db-connection-pool 的使用方法。附带真实的连接数打满事故------一个报表页面并发 200 个请求,MySQL 连接数从 20 飙到 200,数据库直接拒绝新连接。


🎬 个人主页: 源码骑士

专栏传送门: 《Android开发基础》《python基础课程》

⭐️热衷从源码视角拆解技术底层原理,将复杂架构讲得通俗易懂


🎬 源码骑士的简介:

5年Android Framework系统开发经验,曾主导多项系统级性能优化专项

技术栈覆盖Android系统全链路(Binder/Handler/AMS/WMS/启动流程)及Java后端全家桶(Spring + MyBatis + Redis + Oracle)

累计产出原创技术文章100+篇,文章以源码拆解为特色,被读者评价为"看一篇胜过啃一周文档"


导入语

2021 年的一个周一早上,运维在群里发了一张截图------MySQL 的 SHOW PROCESSLIST 显示 200 个活跃连接,其中 180 个状态是 "Sleep"。数据库的最大连接数配置的是 200------新的请求一进来直接 Too many connections。而当时的并发量只有 50 个用户。

排查后发现是 Django 默认的数据库连接模式导致的------每个线程创建一个持久连接,Gunicorn 配置了 100 个 worker 线程,每个线程启动时各自连一次数据库,加上高峰期的一些重连,总数就爆了。加上连接池之后,连接数稳定在 20 以下,同一个问题再也没出现过。


1 ~> 没有连接池时------每个请求都"租房",而不是"住酒店"

1.1 MySQL 连接的生命周期

建立一个 MySQL 连接需要:

bash 复制代码
步骤1:TCP 三次握手 → 1-2ms(同机房)~ 20ms(跨机房)
步骤2:MySQL 认证(用户名/密码验证) → 一点点开销
步骤3:发送 SQL → 接收结果
步骤4:TCP 四次挥手 → 与握手相同

如果每个 HTTP 请求都要经历这些步骤,在高并发时累积开销巨大。 连接池的原理:提前创建好一批连接,请求来了就从池里借一个,用完还回去------几乎零开销。


2 ~> Django 默认的连接行为

Django 默认为每个线程维护一个持久连接(CONN_MAX_AGE 默认 0 表示每个请求结束即关闭,设置为正数则表示连接保留 N 秒):

python 复制代码
# settings.py
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "CONN_MAX_AGE": 600,   # 连接保持 600 秒(10 分钟)
    }
}

问题在于这个模式没有"连接数上限"。 你如果配置了 100 个 Gunicorn worker 线程,就是最多 100 个连接------没有池化管理。


3 ~> django-db-connection-pool------给 Django 加上连接池

3.1 安装配置

bash 复制代码
pip install django-db-connection-pool
python 复制代码
DATABASES = {
    "default": {
        "ENGINE": "dj_db_conn_pool.backends.mysql",  # 替换为池化引擎
        "NAME": "mydb",
        "USER": "root",
        "PASSWORD": os.environ.get("DB_PASSWORD"),
        "HOST": "localhost",
        "POOL_OPTIONS": {
            "POOL_SIZE": 20,          # 池子最大连接数
            "MAX_OVERFLOW": 10,       # 池子满时额外允许创建的临时连接
            "RECYCLE": 3600,          # 连接最大存活时间(秒)
        }
    }
}

3.2 效果

复制代码
没有连接池: 100 个 worker → 可能 100 个数据库连接
用了连接池: 100 个 worker → 最多 20 + 10 = 30 个数据库连接

核心逻辑: 连接池控制了连接数的上限,同时保留了多线程共用的灵活性。当一个线程需要连接时,从池里借;用完还回去,其他线程可以借同一个连接。


4 ~> Java 的 HikariCP 和 Django 连接池的对比

Java 生态中 HikariCP 是连接池的事实标准,它的一些设计有借鉴意义:

HikariCP django-db-connection-pool
连接池大小 默认 10,通常配置为 CPU 核数 * 2 + 1 推荐 20-30
连接泄漏检测 leakDetectionThreshold ❌ 不完善
连接验证 connectionTestQuery 依赖 MySQL 的 ping()
JMX 监控 ✅ 丰富的 Metrics ❌ 较少

5 ~> 连接池的常见误区

"连接池越大越好"------错的。 每个连接在 MySQL 端占用内存(约 256KB-512KB)。如果池子设为 200,数据库可能被连接内存吃满而挤压缓存池空间,反而降低性能。

"有了连接池就不需要关闭连接"------也是错的。 连接池会回收长时间未使用的连接(RECYCLE 参数),但你在应用层应该做的是"用完就还"------不要跨请求持有同一个连接。

Java 开发中的对比:Spring Boot 默认使用 HikariCP,连接池大小通常是 maximumPoolSize = 10。Django 一个中型项目的连接池大小也差不多 20-30。原则一样:够用就行,别贪大。


思考 && 总结

连接池的三个核心价值:

  1. 复用连接------省去 TCP 握手和认证开销(每次请求节省 1-20ms)。
  2. 控制连接数上限 ------防止连接数膨胀撑爆数据库的 max_connections
  3. 连接健康检测------定时回收死连接,避免"借到一根断线"。

结尾

连接池到这里讲完了。感谢阅读!

源码骑士 --- 源码级拆解,从底层看透技术

👀 关注:跟博主一起从源码视角深耕底层原理

❤️ 点赞:让优质内容被更多人看见

收藏:核心知识点存好,随用随查

💬 评论:分享你的经验或疑问,一起交流

🔄 一键四连:别忘了给博主一键四连!

🗡️ 寄语:连接池不是魔法,但那十几毫秒乘以百万次请求,就是一笔时间。

结语:连接池是生产环境的必需品。下篇讲另一个生产必需------密码和密钥到底放哪。一键四连!

相关推荐
叫我:松哥1 小时前
基于Flask的在线考试刷题系统设计与实现,集智能练习、过程追踪、深度分析与个性化引导
数据库·人工智能·后端·python·flask·boostrap
techdashen1 小时前
CPython 仓库 Top 100 贡献者深度分析
python
倒流时光三十年1 小时前
PostgreSQL LEAST 表达式函数详解
数据库·postgresql
thinking_talk1 小时前
2026中国MongoDB云服务厂商能力榜:选型对比与效能评估
数据库·mongodb·腾讯云
dishugj1 小时前
从应用--DB发一条 SQL的数据流向
数据库·oracle
杨云龙UP1 小时前
Oracle 19c 单机环境安装目录规划与磁盘永久挂载操作指南_2026-06-15
运维·服务器·数据库·oracle·部署·目录·规划
码云骑士1 小时前
22-接手Django老项目(下)-读懂urls路由树与架构脉络
python·架构·django
码云骑士1 小时前
29-Python-logging日志模块-print不是日志的生产级实战
开发语言·python
JOJO数据科学1 小时前
DbGate Electron 鸿蒙 PC 适配全记录:从桌面数据库工具到 OpenHarmony HAP
数据库·electron·harmonyos