25-数据库连接池-Django连接复用与连接数上限控制
文章目录数据库连接池到底解决什么问题——不是让连接更快而是让连接活着导入语1 ~ 没有连接池时——每个请求都租房而不是住酒店1.1 MySQL 连接的生命周期2 ~ Django 默认的连接行为3 ~ django-db-connection-pool——给 Django 加上连接池3.1 安装配置3.2 效果4 ~ Java 的 HikariCP 和 Django 连接池的对比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 连接需要步骤1TCP 三次握手 →1-2ms同机房~ 20ms跨机房 步骤2MySQL 认证用户名/密码验证 → 一点点开销 步骤3发送 SQL → 接收结果 步骤4TCP 四次挥手 → 与握手相同如果每个 HTTP 请求都要经历这些步骤在高并发时累积开销巨大。连接池的原理提前创建好一批连接请求来了就从池里借一个用完还回去——几乎零开销。2 ~ Django 默认的连接行为Django 默认为每个线程维护一个持久连接CONN_MAX_AGE默认 0 表示每个请求结束即关闭设置为正数则表示连接保留 N 秒# settings.pyDATABASES{default:{ENGINE:django.db.backends.mysql,CONN_MAX_AGE:600,# 连接保持 600 秒10 分钟}}问题在于这个模式没有连接数上限。你如果配置了 100 个 Gunicorn worker 线程就是最多 100 个连接——没有池化管理。3 ~django-db-connection-pool——给 Django 加上连接池3.1 安装配置pipinstalldjango-db-connection-poolDATABASES{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 是连接池的事实标准它的一些设计有借鉴意义HikariCPdjango-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。原则一样够用就行别贪大。思考 总结连接池的三个核心价值复用连接——省去 TCP 握手和认证开销每次请求节省 1-20ms。控制连接数上限——防止连接数膨胀撑爆数据库的max_connections。连接健康检测——定时回收死连接避免借到一根断线。结尾连接池到这里讲完了。感谢阅读源码骑士 — 源码级拆解从底层看透技术关注跟博主一起从源码视角深耕底层原理❤️点赞让优质内容被更多人看见⭐收藏核心知识点存好随用随查评论分享你的经验或疑问一起交流一键四连别忘了给博主一键四连️寄语连接池不是魔法但那十几毫秒乘以百万次请求就是一笔时间。结语连接池是生产环境的必需品。下篇讲另一个生产必需——密码和密钥到底放哪。一键四连