点击关注公众号,实用技术文章及时了解

来源:blog.csdn.net/lmy86263/article/

details/76165714

背景

开发应用程序久了,总想刨根问底,尤其对一些有公共答案的问题。大家都能解释,但是追根究底,都解释不清。凡是都有为什么,而且用数字说明问题是最直观的。

本文主要想探究一下连接数据库的细节,尤其是在 Web 应用中要使用数据库来连接池,以免每次发送一次请求就重新建立一次连接。

对于这个问题,答案都是一致的,建立数据库连接很耗时,但是这个耗时是都多少呢,又是分别在哪些方面产生的耗时呢?

分析

本文以连接 MySQL 数据库为例,因为 MySQL 数据库是开源的,其通信协议是公开的,所以我们能够详细分析建立连接的整个过程。

在本文中,消耗资源的分析主要集中在网络上,当然,资源也包括内存、CPU 等计算资源,使用的编程语言是 Java,但是不排除编程语言也会有一定的影响。

首先先看一下连接数据库的 Java 代码,如下:

Class.forName("com.mysql.jdbc.Driver");  String name = "shine_user";
String password = "123";
String url = "jdbc:mysql://172.16.100.131:3306/clever_mg_test";
Connection conn = DriverManager.getConnection(url, name, password);
// 之后程序终止,连接被强制关闭

然后通过「Wireshark」分析整个连接的建立过程,如下:

Wireshark 抓包

在上图中显示的连接过程中,可以看出 MySQL 的通信协议是基于 TCP 传输协议的,而且该协议是二进制协议,不是类似于 HTTP 的文本协议。

其中建立连接的过程具体如下:

  • 第 1 步: 建立 TCP 连接,通过三次握手实现。

  • 第 2 步: 服务器发送给客户端「握手信息」,客户端响应该握手消息。

  • 第 3 步: 客户端「发送认证包」,用于用户验证,验证成功后,服务器返回 OK 响应,之后开始执行命令。

用户验证成功之后,会进行一些连接变量的设置,比如字符集、是否自动提交事务等,其间会有多次数据的交互。完成了这些步骤后,才会执行真正的数据查询和更新等操作。

在本文的测试中,只用了 5 行代码来建立连接,但是并没有通过该连接去执行任何操作,所以在程序执行完毕之后,连接不是通过 Connection.close() 关闭的,而是由于程序执行完毕,导致进程终止,造成与数据库的连接异常关闭,所以最后会出现 TCP 的 RST 报文。

在这个最简单的代码中,没有设置任何额外的连接属性,所以在设置属性上占用的时间可以认为是最少的(其实,虽然我们没有设置任何属性,但是驱动仍然设置了字符集、事务自动提交等,这取决于具体的驱动实现),所以整个连接所使用的时间可以认为是最少的。

但从统计信息中可以看出,在不包括最后 TCP 的 RST 报文时(因为该报文不需要服务器返回任何响应),但是其中仍需在客户端和服务器之间进行往返「7」次,「也就是说完成一次连接,可以认为,数据在客户端和服务器之间需要至少往返 7 次」。

从时间上来看,从开始 TCP 的三次握手,到最终连接强制断开为止(不包括最后的 RST 报文),总共花费了:

10.416042 - 10.190799 = 0.225243s = 225.243ms

这意味着,建立一次数据库连接需要 225ms,而这还是还可以认为是最少的,当然「花费的时间可能受到网络状况、数据库服务器性能以及应用代码是否高效的影响」,但是这里只是一个最简单的例子,已经足够说明问题了!

由于上面是程序异常终止了,但是在正常的应用程序中,连接的关闭一般都是通过 Connection.close() 完成的。

代码如下:

Class.forName("com.mysql.jdbc.Driver");  String name = "shine_user";
String password = "123";
String url = "jdbc:mysql://172.16.100.131:3306/clever_mg_test";
Connection conn = DriverManager.getConnection(url, name, password);
conn.close();

_网络抓包_

这样的话,情况发生了变化,主要体现在与数据库连接的断开,如上图:

  • 第 1 步: 此时处于 MySQL 通信协议阶段,客户端发送关闭连接请求,而且不用等待服务端的响应。

  • 第 2 步: TCP 断开连接,4 次挥手完成连接断开。

这里是完整地完成了从数据库连接的建立到关闭,整个过程花费了:

747.284311 - 747.100954 = 0.183357s = 183.357ms

这里可能也有网络状况的影响,比上述的 225ms 少了,但是也几乎达到了 200ms 的级别。

那么问题来了,想象一下这个场景,对于一个日活 2 万的网站来说,假设每个用户只会发送 5 个请求,那么一天就是 10 万个请求。

对于建立数据库连接,我们保守一点计算为 150ms 好了,那么一天当中花费在建立数据库连接的时间有(还不包括执行查询和更新操作):

100000 * 150ms = 15000000ms = 15000s = 250min = 4.17h

也就说每天花费在建立数据库连接上的时间已经达到「4 个小时」,所以说数据库连接池是必须的嘛。

而且当日活增加时,单单使用数据库连接池也不能完全保证你的服务能够正常运行,还需要考虑其他的解决方案。

例如:

  • 缓存

  • SQL 的预编译

  • 负载均衡

  • ……

总结

当然这不是本文的主要内容,本文想要阐述的核心思想只有一个,数据库连接真的很耗时,所以不要频繁的建立连接。

推荐

主流Java进阶技术(学习资料分享)

Java面试题宝典

加入Spring技术开发社区

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!

为什么数据库连接很消耗资源?相关推荐

  1. java反射为什么消耗资源_Java反射笔记

    第一:先认识Class类 类也是一种实例,类的实例创建有三种方式. 类的实例对象创建的方式有两种.以下的代码详细的介绍: packagecom.company;import java.util.*;p ...

  2. 揪出偷偷消耗资源的黑手!

    16340284 [数据科学与计算机学院] (http://sdcs.sysu.edu.cn/) 张山丰 不久前是国庆,相信大家都非常高兴,因为不仅有丰富多彩的假期,还是流量清零重新计算的日期,但不管 ...

  3. mysql如何定义消耗资源多的sql语句_如何查找消耗资源较大的SQL

    对于优化来讲,查找消耗资源较大的SQL至关重要,下面介绍几个之前用到的SQL. 1.从V$SQLAREA中查询最占用资源的查询. select b.username username,a.disk_r ...

  4. oracle消耗资源,oracle中资源消耗查看

    查看会话内存占用情况 SELECT server "连接类型", s.username, OSUSEr, NAME, VALUE/1024/1024 "占用内存MB&qu ...

  5. oracle 消耗资源的语句,oracle查询消耗服务器资源SQL语句

    1.查找最近一天内,最消耗CPU的SQL语句 SELECT ASH.INST_ID, ASH.SQL_ID, (SELECT VS.SQL_TEXT FROM GV$SQLAREA VS WHERE ...

  6. 5G信令(就是用户身份信息)风暴——就是客户端通过公钥加密的消息(携带手机IMSI号)发给服务端,服务器需用私钥解密,这个解密比较消耗资源,如果短时间大量请求到来就会触发信令风暴...

    信令:手机开机后,先从USIM中读取之前运营商分配的临时身份信息GUTI/TMSI,发送携带该身份信息的信令给基站,请求接入运营商网络. 如果每个设备的每条消息都需要单独认证,则网络侧安全信令的验证需 ...

  7. 无线连接服务器会消耗资源么,一秒钟法则:来自腾讯的无线研发经验

    移动互联网的组织形态.架构.通讯机制等等与有线网络都有着巨大的差异,腾讯在处理这种差异的时候都有哪些经验呢? 编者注:本文转自腾讯大讲堂.在 2014 年 4 月 11 日的腾讯分享日活动上,来自腾讯 ...

  8. oracle高资源消耗sql,oracle 中如何定位重要(消耗资源多)的SQL

    在分析SQL性能的时候,经常需要确定资源消耗多的SQL,总结如下: 1查看值得怀疑的SQL selectsubstr(to_char(s.pct,'99.00'),2)||'%'load, s.exe ...

  9. oracle高资源消耗sql,Oracle中定位重要(消耗资源多)的SQL

    在分析SQL性能的时候,经常需要确定资源消耗多的SQL,总结如下: 1 查看值得怀疑的SQLselect substr(to_char(s.pct, 在分析SQL性能的时候,经常需要确定资源消耗多的S ...

最新文章

  1. 机器学习-第六章 支持向量机(SVM)
  2. [java][ide][sts] 使用配置
  3. PyTorch多卡分布式训练:DistributedDataParallel (DDP) 简要分析
  4. JavaScript操作BOM简单案例
  5. 杭州·云栖大会宣布多款核心云产品降价,最高降幅达90%
  6. java 字符串排列_Java实现字符串的全排列
  7. python极简代码实现快速排序
  8. 多出20倍?Android 收集用户数据量远超 iPhone
  9. 全球最厉害的14位程序员
  10. 解决win7能上网却右下角网络图标显示红色叉号的问题
  11. 第六章节 多态 (多态的概述)
  12. 《Ext JS权威指南》节选:树的动态加载及节点维护
  13. net use远程重启服务器
  14. 745. 前缀和后缀搜索(每日一难phase2--day27)
  15. [学习日志]UI如何与数据绑定?
  16. python超清壁纸_python爬虫 爬取超清壁纸代码实例
  17. jQuery简易的购物车
  18. [JZOJ3339]【NOI2013模拟】wyl8899和法法塔的游戏
  19. 外推法的matlab程序
  20. 曲线拟合的最小二乘原理

热门文章

  1. 苹果设备频繁杀后台问题在iOS 13.2.2正式版更新后得以抑制
  2. 华为nova 5z即将亮相:麒麟810+3200万人像超级夜景
  3. 一加7T Pro曝光:10月10日发布
  4. 为真全面屏探路?2019款新iPhone将采用超小前置摄像头
  5. 基于exosip的uas-uac的一个简单例子(转载)
  6. android去除标题栏
  7. 线性表:3.链表,单链表详解与C语言实现
  8. 爬虫教程 python3_【Python3爬虫】Appium入门教程
  9. appcrash事件怎么解决_突发事件中身心容易紧张焦虑,该如何控制心理压力与情绪?...
  10. 基于神经网络预测车道行驶的自动驾驶