背景开发应用久了,总想一探究竟,尤其是一些有公开答案的问题。每个人都可以解释,但归根结底,他们无法解释清楚。凡事都是有原因的,用数字来说明问题是最直观的。这篇文章主要是想探讨一下连接数据库的细节,尤其是在web应用中使用数据库连接池,以免每次发送请求都要重新建立连接。对于这个问题,答案是一样的。建立数据库连接是很耗时的,但是这个耗时是多少,耗时在哪些方面呢?分析本文以连接MySQL数据库为例。由于MySQL数据库是开源的,其通信协议也是开放的,我们可以详细分析建立连接的整个过程。另外,MySQL系列面试题和答案都整理好了。微信搜索Java技术栈,后台发送:面试,可以在线阅读。在本文中,资源消耗的分析主要集中在网络上。当然,资源还包括内存、CPU等计算资源。使用的编程语言是Java,但不排除编程语言也会有一定的影响。先看Java连接数据库的代码,如下:Class.forName("com.mysql.jdbc.Driver");Stringname="shine_user";Stringpassword="123";Stringurl="jdbc:mysql://172.16.100.131:3306/clever_mg_test";Connectionconn=DriverManager.getConnection(url,name,password);//程序终止后,强行关闭连接然后通过"分析整个连接建立过程Wireshark”,如下:在图中所示的连接过程中,可以看出MySQL的通信协议是基于TCP传输协议的,协议是二进制协议,不是类似HTTP的文本协议。建立连接的过程如下:第一步:通过三次握手建立TCP连接。第二步:服务器向客户端发送“握手消息”,客户端响应握手消息。第三步:客户端“发送认证包”进行用户认证。认证成功后,服务器返回OK响应,然后开始执行命令。用户认证成功后,会设置一些连接变量,比如字符集,是否自动提交交易等,这期间会有多次数据交互。这些步骤完成后,才进行真正的数据查询和更新操作。在本文的测试中,只用了5行代码来建立连接,但是并没有通过连接进行任何操作,所以程序执行后,连接并没有被Connection.close()关闭,而是因为程序执行完成后进程终止,与数据库的连接异常关闭,所以最后会出现TCPRST报文。在这个最简单的代码中,没有设置额外的连接属性,所以设置属性所花费的时间可以认为是最少的(事实上,虽然我们没有设置任何属性,但驱动程序仍然设置了字符集,事务是自动的committed等,取决于具体的驱动实现),所以整个连接使用的时间可以认为是最少的。但是从统计信息可以看出,当不包括最后一条TCPRST报文时(因为这条报文不需要服务器返回任何响应),但是客户端和服务器之间仍然有“7”次往返,"也就是说,要完成一次连接,可以认为数据至少需要在客户端和服务器之间来回7次。"从时间上来说,从TCP三次握手开始到最终连接被强制断开(不包括最后的RST报文),一共耗时:10.416042-10.190799=0.225243s=225.243ms这意味着一个数据库连接建立需要225ms,这还是可以认为是最小的。当然,“花费的时间可能会受到网络状况、数据库服务器性能、应用程序代码效率的影响”,但这里只是最简单的例子,足以说明问题!由于上面是程序异常终止,但是在正常的应用中,连接的关闭一般是通过Connection.close()来完成的。代码如下:Class.forName("com.mysql.jdbc.Driver");Stringname="shine_user";Stringpassword="123";Stringurl="jdbc:mysql://172.16.100.131:3306/clever_mg_test";Connectionconn=DriverManager.getConnection(url,name,password);conn.close();这种情况下,情况发生了变化,主要体现在与数据库的连接断开,如上图所示:第一步:此时,在MySQL的通信协议阶段,客户端发送请求关闭连接而不等待服务器的响应。第二步:TCP断开,4次挥手完成连接断开。这里完整的完成了从建立数据库连接到关闭的整个过程:747.284311-747.100954=0.183357s=183.357ms这里可能也是受网络情况的影响,比上面的225ms少了,但是也差不多了200毫秒级别。那么问题来了。想象一下这种情况。对于一个日活跃用户2万的网站,假设每个用户只发送5次请求,那么每天有10万次请求。对于建立数据库连接,我们保守计算为150ms,那么一天建立数据库连接所花费的时间(不包括查询和更新操作):100000*150ms=15000000ms=15000s=250min=4.17h据说每天建立数据库连接的时间已经达到“4小时”,所以需要数据库连接池。而当日常活动增多时,单靠数据库连接池并不能完全保证你服务的正常运行,需要考虑其他的解决方案。例如:缓存SQL的预编译负载均衡……总结当然,这不是本文的主要内容。本文想说明的核心思想只有一个。数据库连接真的很费时间,所以不要频繁建立连接。版权声明:本文为CSDN博主“lmy86263”原创文章,遵循CC4.0BY-SA版权协议。转载请附上原文出处链接及本声明。
