dbaplus社群 2024年11月11日
为什么数据库连接很消耗资源?被问根本答不出来……
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入探讨了连接数据库的耗时问题,以MySQL数据库为例,通过Java代码和Wireshark网络分析工具,详细分析了建立数据库连接的整个过程,包括TCP三次握手、服务器握手信息、客户端认证等步骤。研究发现,建立一次数据库连接平均耗时约为200ms,即使是最简单的连接操作也需要客户端和服务器之间多次数据交互。作者通过计算,说明了在高并发场景下,频繁建立数据库连接会导致大量时间浪费,从而强调了数据库连接池的重要性,以及在高负载情况下需要考虑缓存、负载均衡等其他解决方案。

🤔 **连接数据库耗时分析:**文章以MySQL为例,通过Java代码和Wireshark分析,详细描述了建立数据库连接的步骤,包括TCP三次握手、服务器握手信息、客户端认证等,并指出建立一次连接至少需要客户端和服务器之间往返7次数据交互。

⏱️ **连接耗时约200ms:**在测试中,建立一次数据库连接耗时约为225ms,即使没有执行任何操作,也需要客户端和服务器之间多次交互,并且该时间会受到网络状况、数据库服务器性能等因素影响。

🏊 **数据库连接池的必要性:**文章通过计算,说明了在高并发场景下,频繁建立数据库连接会导致大量时间浪费,例如,一个日活2万的网站,每天可能需要花费4个小时在建立数据库连接上,因此数据库连接池是必要的优化手段。

🔄 **其他优化方案:**除了数据库连接池,文章也提到了在高负载情况下,还可以考虑其他优化方案,例如缓存SQL预编译、负载均衡等,以进一步提升数据库性能。

2024-11-11 07:15 广东

耗时是多少?又是分别在哪些方面产生的耗时呢?




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





本文主要想探究一下连接数据库的细节,尤其是在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分析整个连接的建立过程,如下:



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



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


在本文的测试中,只用了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();


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




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


747.284311 - 747.100954 = 0.183357s = 183.357ms


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


那么问题来了,想象一下这个场景,对于一个日活2万的网站来说,假设每个用户只会发送5个请求,那么一天就是10万个请求,对于建立数据库连接,我们保守一点计算为150ms好了,那么一天当中花费在建立数据库连接的时间有(还不包括执行查询和更新操作):


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


也就说每天花费在建立数据库连接上的时间已经达到4个小时,所以说数据库连接池是必须的嘛,而且当日活增加时,单单使用数据库连接池也不能完全保证你的服务能够正常运行,还需要考虑其他的解决方案:



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


作者丨lmy86263

来源丨网址:https://blog.csdn.net/lmy86263/article/details/76165714

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn


活动推荐


为了和大家一起探索AI相关技术在大数据、数据资产管理、数据库、运维等领域的最佳落地方式,挖掘由此激发的软件发展和技术进步,第九届DAMS中国数据智能管理峰会将于2024年11月29日在上海举办,携手一众产学研界技术领跑单位,带来新思路、重实践、可落地的全日干货盛宴。早鸟优惠,码上报名↓


跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

数据库连接 连接池 MySQL 性能优化 网络通信
相关文章