大数跨境
0
0

数据库设计哲学4:池化

数据库设计哲学4:池化 程序猿读历史
2025-08-15
5
导读:池化是提升数据库性能与稳定性的重要手段。尽管连接池最为人熟知,但池化技术在数据库中应用广泛,如连接池、线程池、对象池、缓冲池等,均体现了对资源的高效复用与管理。
数据库设计哲学1:空间换时间
数据库设计哲学2:分而治之
数据库设计哲学3:局部性
池化是本系列的第四篇,也是最后一篇,前三篇分别聊了数据库中的空间换时间、分而治之、局部性等设计思想。

说到池化,很多人会第一时间想到数据库中的连接池。的确,数据库连接池是最能体现池化思想的经典设计,它充分体现了“需要时动态地分配和重用资源,避免频繁创建和销毁”的理念。

什么是池化

池化(Pooling),本质上是一种资源预分配与复用机制。它的核心思想是:将一组昂贵或创建成本高的资源提前准备好,放入一个“池”中,当系统需要使用时,从池中取出;使用完毕后,并不立即销毁,而是归还至池中,供后续请求复用。

池化模式与 “即用即建、用完即毁” 的资源管理方式差异显著。当数据库中的资源创建销毁成本较高场景下,后者在高并发场景下,会因资源频繁启停产生高昂开销,甚至引发资源竞争、内存抖动等系统性瓶颈。

实际上,池化思想在我们生活中也处处可见,比如农村中的水池。当需要使用水,村民无需每次用水都临时水桶接水,而是直接从水池中取水,实现随用随取;使用完成后,水池也不会用后即弃,可循环使用。这种方式既提升了用水效率,也让取水成本长期可控。

类似地,共享自行车、共享充电宝都是池化思想的体现,通过集中储备和循环使用,提升资源利用效率,降低获取成本。

池化技术的核心原理

池化技术是通过 预分配、复用、管理 三大关键步骤,规避资源频繁创建 / 销毁的高昂成本,实现资源高效利用,核心逻辑可拆解为以下三点。

  • 提前创建资源池在系统启动或低负载时,提前创建一批可用状态的资源,集中存入一个 资源池”中,避免需要时才临时创建。

  • 按需取用与循环复用在业务需要资源时,直接从池中获取已就绪的资源,无需重新创建;当使用完毕后,不直接销毁资源,而是将清空连接数据、恢复线程初始状态等操作将资源并放回池中,供后续需求重复使用。

  • 动态管理与监控池化技术会配套管理机制,比如设置池大小上限防止资源过度占用,最小空闲数保证低负载时快速响应,以及 超时回收清理长期闲置资源,平衡 资源利用率与 系统开销。

池化技术的具体应用

连接池

连接池是数据库中最常见的池化应用,也是数据库优化的重要手段。数据库连接的建立是典型的高成本操作,需要经过多次的TCP 握手、用户密码校验、会话初始化等大量消耗系统资源的步骤。而连接池是通过预先创建一定数量的连接并维护在 “池” 中,让请求直接复用现成连接,避免了频繁创建销毁的开销。

MySQL SQL 执行过程,图来自互联网

常见的MySQL连接池有Tomcat JDBC Pool、C3P0、Druid以及HikariCP,其中轻量级的HikariCP 号称性能杀手。下图是HikariCP 给出的性能测试报告。

连接池性能对比,图来自HikariCP 

线程池

数据库线程池是基于池化思想优化数据库连接管理的技术,通过预先创建并在内存中维护一定数量的数据库连接,实现连接的快速获取与释放,进而提升数据库访问的性能与稳定性。以MySQL 为例。

MySQL是单进程多线程的模式,线程调度方式是 one-thread-per-connection(每个连接一个线程)。当有请求时,MySQL为每一个连接创建一个线程来服务;请求结束后,线程释放。和连接池相同逻辑,线程池的创建非常消耗资源,为了解决这个问题,MySQL的多个发行版本都推出了连接池方案。

不过遗憾的是官方MySQL 线程池是作为插件的形式存在,目前只在企业版中支持,只有MariaDB和Percona 的版本中是支持线程池功能。

MySQL线程池性能测试,图来自MySQL Blog

MySQL 8.0 使用线程池时,随着用户连接数的增加,性能得以维持。在没有使用线程池,在达到 64 个连接后,TPS开始下降,在4096 连接数开始TPS 大约只有 900 ;而使用线程池,在 4096 连接数下,TPS 依旧可以到达7000。

对象池

对象池就是一定数量的已经创建好的数据库对象集合。当需要使用对象时,先在池中获取,如果池中没有符合条件的对象,再进行对象创建;当对象需要销毁时,将其置为不可用并存入池子中。这样就避免了大量对象的频繁创建、销毁。

以一条SQL 执行为例。我们知道一条 SQL 语句在数据库中从接收到最终执行完毕返回,其大致流程如下:

建立连接;词法和语义解析;执行计划的选择;执行并返回结果;

如果这条SQL 语句会被反复执行,或者每次执行的时候只是具体值不同,比如 where id ='xx'。数据库在执行这样的SQL时,还是每次都需要经过建立连接、词法语义解析、语句优化、制定执行计划等,那么性能是低效的。

数据库会通过预编译语句,就是将这类SQL 中的值用占位符替代,实现语句模板化或者说参数化,在数据库里将这类语句叫 Prepared Statements。

总结

除上述设计外,数据库中的内存池、缓存池、查询结果缓存等,同样通过优化连接、内存、线程、SQL 编译等场景提升性能。掌握数据库池化思想,关键不在于仅会配置连接池、线程池,而在于理解如何在资源有限时,借助预分配与复用构建高效、稳定、可扩展的系统。在应用工程编码上也可以借助池化思想。

回顾本系列四篇内容,可以做以下简单概括:

  • 空间换时间:用存储换取计算效率;

  • 分而治之:将大问题拆解为可管理的小单元;

  • 局部性:利用访问模式的聚集性提升缓存效率;

  • 池化:通过资源复用降低开销,提升系统韧性。

实际上,在数据库这四种思想是相互交织、协同作用,比如缓冲池既体现了池化思想,也体现了局部性和空间换时间。

参考

https://github.com/brettwooldridge/HikariCP?tab=readme-ov-file

https://dev.mysql.com/doc/refman/8.4/en/thread-pool-operation.html MySQL 

https://dev.mysql.com/blog-archive/the-new-mysql-thread-pool/ 

图片

作者介绍

司马辽太杰,10余年数据库架构和运维管理经验,擅长常见关系型、NoSQL、MPP 等类型数据库。业余热爱历史、足球,读点闲书。欢迎关注个人公众号“程序猿读历史”。需联系,可从关注公众号,在公众号对话窗口中扫码添加好友。感谢您的支持!

图片

【声明】内容源于网络
0
0
程序猿读历史
这是一位数据库从业者以及历史爱好者的个人公众号。
内容 87
粉丝 0
程序猿读历史 这是一位数据库从业者以及历史爱好者的个人公众号。
总阅读94
粉丝0
内容87