前段时间在一个老项目中经历过一个问题:一个 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的配置可以在全局变量中查询和设置,相关的配置主要可以查询下面这些:

3. 连接池设置多少连接才合适

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

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

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

这里有一个 Oracle 性能小组发布的简短视频,连接池测试分2个部分:

测试视频1
https://apexapps.oracle.com/p...:112:11510768535381::::P112_CONTENT_ID:9565

测试视频2
https://apexapps.oracle.com/p...:112:11510768535381::::P112_CONTENT_ID:9566

视频中调整了线程池大小为2048的时候数据库性能陡然下降,后面调整到144就恢复了。PostgreSQL提供了一个设置预期线程池大小的公式:

connections = ((core_count * 2) + effective_spindle_count)

该公式来自于:https://github.com/brettwoold...。

其中,core_count是CPU核心, effective_spindle_count 的含义是有效主轴数,如果你的服务器使用的是带有16个磁盘的RAID,那么valid_spindle_count=16。它实质上是服务器可以管理多少个并行I / O请求的度量。旋转硬盘一次(通常)一次只能处理一个I / O请求,如果你有16个,则系统可以同时处理16个I / O请求。

我想 Hikari 作为目前最优秀的数据库连接池之一,提出的这个公式还是经得起检验的。大家不妨在生产环境试试(出问题别找我)。

转载 https://segmentfault.com/a/1190000021710378

数据库连接池连接数量配置多大合理相关推荐

  1. 数据库连接池到底应该设多大?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:kelgon www.jianshu.com/p/a8f65 ...

  2. 数据库连接池到底应该设多大?这次直接从100ms优化到3ms!

    点击上方"果汁简历",选择"置顶公众号" 我在研究HikariCP(一个数据库连接池)时无意间在HikariCP的Github wiki上看到了一篇文章(即前面 ...

  3. mysql事务锁导致tomcat崩溃_数据库连接池连接耗尽,导致tomcat请求无响应,呈现出假死状态...

    最困难的事情就是认识自己! 个人网站 ,欢迎访问! 前言:最近,测试部门的同事找到我,说他们测试时,没一会就发现服务接口请求一直无响应,Tomcat跟死掉了一样,也没有返回任何的错误响应,说让我赶紧排 ...

  4. Alibaba Druid 源码阅读(五)数据库连接池 连接关闭探索

    Alibaba Druid 源码阅读(五)数据库连接池 连接关闭探索 简介 在上文中探索了数据库连接池的获取,下面接着初步来探索下数据库连接的关闭,看看其中具体执行了那些操作 连接关闭 下面的具体的代 ...

  5. 阿里巴巴 Druid 数据库连接池监控界面配置的参数解读

    阿里巴巴 Druid 数据库连接池监控界面配置的参数解读 1.可选的配置项 Property Name Default Value Remarks name 存在多个数据源的时候用于识别数据源 jdb ...

  6. net core mysql 连接池_EF Core 小坑:DbContextPool 会引起数据库连接池连接耗尽

    EF Core 小坑:DbContextPool 会引起数据库连接池连接耗尽 发布时间:2019-02-18 22:05, 浏览次数:1152 , 标签: EF Core DbContextPool ...

  7. 数据库连接池连接异常com.alibaba.druid.pool.GetConnectionTimeoutException

    数据库连接池连接异常com.alibaba.druid.pool.GetConnectionTimeoutException 参考文章: (1)数据库连接池连接异常com.alibaba.druid. ...

  8. ef mysql 连接数_EF Core 小坑:DbContextPool 会引起数据库连接池连接耗尽

    原标题:EF Core 小坑:DbContextPool 会引起数据库连接池连接耗尽 DbContextPool 是 ASP.NET Core 2.1 引入的新特性,可以节省创建 DbContext ...

  9. oracle mysql连接池配置文件_数据库连接池两种配置方式详解

    数据库连接池: 负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而再不是重新建立一个:释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接 ...

最新文章

  1. 代码优化实战:我又优化了一百个if else!
  2. 黑客帝国真的可以!这100万个「活体人脑细胞」5分钟学会打游戏
  3. notepad++ 设置编辑区域背景色为黑色
  4. 网站优化过度后会出现哪些“后遗症”?悠着点~
  5. SAP UI5 初学者教程之十四 - 嵌入视图的使用方式试读版
  6. 贝叶斯学派,先验概率,后验概率,贝叶斯估计
  7. 软件测试流程-全程软件测试【全思维导图】最新总结
  8. 在线凯撒密码自动分析工具
  9. MATLAB 绘制柱状图
  10. qt多级菜单_Qt高仿电脑管家界面(二):点击按钮弹出菜单
  11. 傻X了:mac上编译的程序放到linux上运行
  12. Received empty response from Zabbix Agent at [agent]. Assuming that agent dropped connection because
  13. 用matlab求二重积分例题_matlab计算二重积分
  14. 哪些语句在python中非法_下列语句中,在Python中是非法的
  15. 数据存储设备的发展历史
  16. type转HDMI2.0方案|typec转HDMI 4K60Hz电路|CS5265 typec单转优势方案
  17. 苏菲兔子和魔法师小麦
  18. 如何向天翼云服务器上传文件,天翼云储存上传文件的方法
  19. 6个做好网站SEO必不可少的方法
  20. android强制缓存写磁盘,Android缓存之DiskLruCache磁盘缓存的使用

热门文章

  1. 前端H5实现微信授权
  2. Binder机制之AIDL
  3. jquery把页面<table>里的内容导出为后缀名为.xlsx的excel
  4. Python爬虫之入门保姆级教程,学不会我去你家刷厕所
  5. python基础-命名规则
  6. [Python人工智能] 一.神经网络入门及theano基础代码讲解
  7. [4G5G专题-68]:物理层 - 4G LTE物理广播信道PBCH与主信息块MIB
  8. 什么工程项目管理软件好用?
  9. 编程练习:非质数分解成质数相乘
  10. tomcat启动报错javax.servlet.ServletException: It is not allowed to configure supportsCredentials=[true]