关于java:面试官为什么数据库连接很消耗资源我竟然答不上来一下懵了

65次阅读

共计 2534 个字符,预计需要花费 7 分钟才能阅读完成。

背景

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

本文次要想探索一下连贯数据库的细节,尤其是在 Web 利用中要应用数据库来连接池,免得每次发送一次申请就从新建设一次连贯。

对于这个问题,答案都是统一的,建设数据库连贯很耗时,然而这个耗时是都多少呢,又是别离在哪些方面产生的耗时呢?

剖析

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

另外,MySQL 系列面试题和答案全副整顿好了,微信搜寻​Java 技术栈,在后盾发送:面试,​能够在线浏览。

在本文中,耗费资源的剖析次要集中在网络上,当然,资源也包含内存、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」剖析整个连贯的建设过程,如下:

在上图中显示的连贯过程中,能够看出 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 的预编译
  • 负载平衡
  • ……

总结

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

版权申明:本文为 CSDN 博主「lmy86263」的原创文章,遵循 CC 4.0 BY-SA 版权协定,转载请附上原文出处链接及本申明。
原文链接:https://blog.csdn.net/lmy8626…

近期热文举荐:

1.1,000+ 道 Java 面试题及答案整顿 (2022 最新版)

2. 劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4. 别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!

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

感觉不错,别忘了顺手点赞 + 转发哦!

正文完
 0