数据库连接池设置多少连接才合适?

作者: rickiyang
出处:https://www.cnblogs.com/rickiyang/p/12239907.html

前段时间在一个老项目中经历过一个问题:一个 Dubbo 服务,启动的时候慢的要死,后来看日志查原因整个过程一直在初始化数据库连接。一看数据库连接参数,连接池大小:1024。

很多入行晚的同学没有经历过手写 JDBC 连接的日子。那个时候没有数据库连接池的概念,都是原生代码一顿搞,后来有了 iBATIS 之后 Java 开发的繁杂程度才逐渐减轻,也衍生 C3P0 数据库连接池这种基础的东西。

罗马不是一天建成的,可是互联网发展太快了,技术压力逼迫下各种中间件被迫研发,大家加班加点搞出来各种高大上的脚手架,也成就很多伟人

数据库连接使用 TCP 的方式,建立连接需要3次握手,释放连接需要4次挥手,当今这种互联网使用频率下,如果每一次访问数据库都重新建立连接,我估计你们公司倒闭800次都不够。

1. 数据库连接的过程是怎样的

Java 鼻祖 Sun 公司是想以一套API统一天下,奈何各个数据库服务器厂商太给力统一不了。无奈之举是创建了一个统一的接口,提出一套统一接入的步骤,各个厂商实现接口,按照步骤加载自己的数据库。所以现在的方案就是4板斧:

  1. 注册驱动,为人所知的:Class.forName()
  2. 获取Connection,成功即与数据库建立连接;
  3. 拿到Statement对象,用于操作数据库的CRUD;
  4. 获取数据库返回结果ResultSet。

大家应该都知道数据库本身是一个客户端程序,只有启动了才能连接。拿 MYSQL 举例,我们在安装并启动了服务的机器上,命令行的方式输入:mysql -uroot -p 即可连接当前数据库。

MYSQL 连接方式有很多种,区分Unix系统 和 Windows 系统以及通用的连接方式,在这里仅说两种方式:一种为 unix domain socket,另外一种为基于 tcp/ip 协议,一般我们如果远程访问数据库肯定是基于 tcp/ip 的,但是如果我们在本机登录就会分为使用 socket 还是 tcp/ip。

socket:mysql -uroot -p
tcp/ip:mysql -h127.0.0.1 -uroot -p

当数据库服务器和应用服务器位于不同的主机时就要使用 tcp/ip 的方式建立连接。每一个连接在操作系统中占用一个线程来维护。建立连接也分为两类:短连接和长连接。

短连接

所谓短连接就是指应用程序和数据库通信完毕之后连接关闭。这种连接每次的操作就是:

发出请求--->建立连接--->操作数据--->释放连接

这样做的问题是:

  1. 频繁的建立 / 释放连接对数据库来说增加了系统负担;
  2. 应用程序每次操作数据库的过程将会变得很慢;
  3. 应用系统每次建立连接都要占用一个端口,频繁的建立/释放,每个被释放的连接在发出释放请求之后并不是马上就执行,必须经历一个 FIN 阶段的等待直到确认为止。所以在每秒几千次数据库请求的时候,应用服务器端口很有可能被消耗完。

长连接

长连接即在建立连接后一直打开,直到应用程序关闭才释放。使用长连接的好处是减少每次创建连接带来的开销。

对于应用服务器来说维持长连接的好处不言自明,但是对于数据库服务器来说,过多的长连接则是灾难。

MYSQL的TCP连接支持长连接,所以每次操作完数据库,可以不必直接关掉连接,而是等待下次使用的时候在复用这个连接。所有的Socket长连接都是通过TCP自带的ping来维持心跳(TCP保活),从而保持连接状态,而我们熟悉的websocket,也正是通过TCP的心跳来维持连接不被中断。

连接池

长连接的好处这么大,自然大家都用长连接。慢慢就搞出一套长连接维护的工具 - 数据库连接池。

设计连接池也没有多么复杂,大致的步骤就是:

  1. 初始化连接;
  2. 业务取出连接;
  3. 业务发送请求;
  4. 放回连接。

除了上面的基本功能以外,还要处理并发问题,多数据库服务器和多用户,事务处理,连接池的配置与维护。大概就这些功能。有了连接池之后,连接的建立和释放跟业务就没有关系,交给交接池来维护。

2. MYSQL 能支持多少连接

MYSQL 的最大连接数在5.7版本中默认是151, 最大可以达到16384(2^14)。如何设置最大连接数在于你的服务器性能,查看 MYSQL连接数信息命令如下:

mysql> show variables like '%max_connections%';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 5050  |
+-----------------+-------+
1 row in set (0.00 sec)

我们生产环境MYSQL的最大连接数设置为 5050,注意不能设置的太小,太小造成的后果是连接失败:“query failed Error 1040: Too many connections“ 错误。太大且当连接该数据库的机器比较多的时候则会对当前MYSQL的性能产生影响。

MYSQL官网给出了一个设置最大连接数的建议比例:

Max_used_connections / max_connections * 100% ≈ 85%

即已使用的连接数占总上限的85%左右,如果目前已使用的连接数与最大连接数比例小于10%那很显然设置的过大。

查询当前数据库已建立连接数:

mysql> show status like 'Threads_connected';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 89    |
+-------------------+-------+
1 row in set (0.00 sec)

Mysql的配置可以在全局变量中查询和设置,相关的配置主要可以查询下面这些:

配置含义
Connections尝试连接Mysql的连接数,不管连接成功与否,该值都会+1
Threads_connected已经建立的连接数,单节点下一般小于最大连接池最大连接数
max_connectionsMysql限制的最大的可连接的数量
wait_timeout即MYSQL长连接(非交互式)的最大生命时长,默认是8小时
interactive_timeout长连接(交互式)的最大生命时长,默认是8小时
3. 连接池设置多少连接才合适

设置连接池的大小肯定不是越大越好,需要考虑的是当前服务所在机器的性能,网络状况,数据库机器性能,数据库特性等等。同时也要做到不浪费系统资源,内存,端口,同步信号量等等。

比如说应用服务器Tomcat设置的最大线程池缺省值200,最大假设每个线程会用到一个数据库连接,那么线程池大小应该小于等于200。

另外需要考虑的是,每申请一个长连接都会在物理网络上建立一个用于长连接维护的进程,而进程的执行跟物理机的CPU核数有关。理论上一个8核的服务器将连接池设置为8最佳,每一个核同时处理一个线程,超过8的并发就有线程上下文切换的开销。

这里有一个 Oracle 性能小组发布的简短视频,连接池测试分2个部分,视频中调整了线程池大小为2048的时候数据库性能陡然下降,后面调整到144就恢复了。

PostgreSQL提供了一个设置预期线程池大小的公式:

connections = ((core_count * 2) + effective_spindle_count)

该公式来自于:

https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing。

其中,core_count是CPU核心, effective_spindle_count 的含义是有效主轴数,如果你的服务器使用的是带有16个磁盘的RAID,那么valid_spindle_count=16。它实质上是服务器可以管理多少个并行I / O请求的度量。

旋转硬盘一次(通常)一次只能处理一个I / O请求,如果你有16个,则系统可以同时处理16个I / O请求。

我想 Hikari 作为目前最优秀的数据库连接池之一,提出的这个公式还是经得起检验的。

近期热文推荐:

1.600+ 道 Java面试题及答案整理(2021最新版)

2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香!

3.阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

4.Spring Cloud 2020.0.0 正式发布,全新颠覆性版本!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
数据库优化方案设计 XX信息管理平台从大型数据库环境四个不同级别的调整分析入手,分析数据库平台的系 统结构和工作机理,从九个不同方面设计数据库的优化方案。 对于数据库的数据优化,主要有四个不同的调整级别,第一级调整是操作系统级包括硬 件平台,第二级调整是RDBMS级的调整,第三级是数据库设计级的调整,最后一个调整级 是SQL级。通常依此四级调整级别对数据库进行调整、优化,数据库的整体性能会得到很 大的改善。下面从九个不同方面介绍数据库优化设计方案。 一、数据库优化自由结构 数据库的逻辑配置对数据库性能有很大的影响。为此,数据库平台一般对表空间设计提 出有相应的优化结构,如ORACLE公司的OFA(Optimal flexible Architecture),使用这种结构进行设计会大大简化物理设计中的数据管理。优化自由结 构,简单地讲就是在数据库中可以高效自由地分布逻辑数据对象,因此首先要对数据库 中的逻辑对象根据他们的使用方式和物理结构对数据库的影响来进行分类,这种分类包 括将系统数据和用户数据分开、一般数据和索引数据分开、低活动表和高活动表分开等 等。 数据库逻辑设计的结果应当符合下面的准则: 把以同样方式使用的段类型存储在一起; 按照标准使用来设计系统; 存在用于例外的分离区域; 最小化表空间冲突; (5)将数据字典分离。 二、充分利用系统全局区域 系统全局区域是数据库平台的心脏,如Oracle数据库的SGA(SYSTEM GLOBAL AREA) 。用户的进程对这个内存区发送事务,并且以这里作为高速缓存读取命中的数据 ,以实现加速的目的。正确的SGA大小对数据库的性能至关重要。SGA包括以下几个部分 : 1、数据块缓冲区(data block buffer cache)是SGA中的一块高速缓存,占整个数据库大小的1%- 2%,用来存储从数据库重读取的数据块(表、索引、簇等),因此采用least recently used (LRU,最近最少使用)的方法进行空间管理。 2、字典缓冲区。该缓冲区内的信息包括用户账号数据、数据文件名、段名、盘区位置、 表说明和权限,它也采用LRU方式管理。 3、重做日志缓冲区。该缓冲区保存为数据库恢复过程中用于前滚操作。 4、SQL共享池。保存执行计划和运行数据库的SQL语句的语法分析树。也采用LRU算法管 理。如果设置过小,语句将被连续不断地再装入到库缓存,影响系统性能。 另外,SGA还包括大池、JAVA池、多缓冲池。但是主要是由上面4种缓冲区构成。对这些 内存缓冲区的合理设置,可以大大加快数据查询速度,一个足够大的内存区可以把绝大 多数数据存储在内存中,只有那些不怎么频繁使用的数据,才从磁盘读取,这样就可以 大大提高内存区的命中率。 三、规范与反规范设计数据库 1、规范化 范式是符合某一级别的关系模式的集合,根据约束条件的不同,一般有1NF、2NF、3NF三 种范式。规范化理论是围绕这些范式而建立的。规范化的基本思想是逐步消除数据依赖 中不合适的部分,使模式中的各关系模式达到某种程度的"分离",即采用"一事一地"的 模式设计原则,因此,所谓规范化实质上就是概念的单一化。数据库中数据规范化的优 点是减少了数据冗余,节约了存储空间,相应逻辑和物理的I/O次数减少,同时加快了增 、删、改的速度。但是一个完全规范化的设计并不总能生成最优的性能,因为对数据库 查询通常需要更多的连接操作,从而影响到查询的速度。故有时为了提高某些查询或应 用的性能而有意破坏规范规则,即反规范化。 2、反规范化 反规范的必要性 是否规范化的程度越高越好呢?答案是否定的,应根据实际需要来决定,因为"分离"越 深,产生的关系越多,结构越复杂。关系越多,连接操作越频繁,而连接操作是最费时 间的,在数据库设计中特别对以查询为主的数据库设计来说,频繁的连接会严重影响查 询速度。所以,在数据库的设计过程中有时故意保留非规范化约束,或者规范化以后又 反规范,这样做通常是为了改进数据库的查询性能,加快数据库系统的响应速度。 反规范技术 在进行反规范设计之前,要充分考虑数据的存取需求,常用表的大小、特殊的计算、数 据的物理存储等。常用的反规范技术有合理增加冗余列、派生列,或重新组表几种。反 规范化的好处是降低连接操作的需求、降低外码和索引数目,减少表的个数,从而提高 查询速度,这对于性能要求相对较高的数据库系统来说,能有效地改善系统的性能,但 相应的问题是可能影响数据的完整性,加快查询速度的同时降低修改速度。 3、数据库设计中的优化策略 数据应当按两种类别进行组织:频繁访问的数据和频繁修改的数据。对于频繁访问但是 不频繁修改的数据,内部设计应当物理不规范化。对于频繁修改但并不频繁访问的数据 ,内部设计应当物理规范化。比较复杂的方法是将规范

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java技术栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值