开发应用程序久了,总想刨根问底,尤其对一些有公共答案的问题。很多答案大家都能说上几句,但追根究底,却解释不清。凡事都有为什么,用数字说明问题往往最直观。
本文主要想探究一下连接数据库的细节,尤其是在 Web 应用中要使用数据库连接池,以免每次发送请求都重新建立一次连接。对于这个问题,答案基本一致:建立数据库连接很耗时。但这个耗时到底是多少?又分别在哪些阶段产生?
本文以连接 MySQL 数据库为例,因为 MySQL 数据库是开源的,通信协议也是公开的,所以能够详细拆解连接建立的全过程。
在本文中,资源消耗分析主要集中在网络上。当然,资源也包括内存、CPU 等计算资源。代码使用 Java 编写,但不能排除编程语言本身也会带来一定影响。
先看一段最简单的 Java 建连代码:
Class.forName("com.mysql.jdbc.Driver");
String name = "xttblog2";
String password = "123456";
String url = "jdbc:mysql://172.16.100.131:3306/xttblog2";
Connection conn = DriverManager.getConnection(url, name, password);
// 之后程序终止,连接被强制关闭
接着用 Wireshark 抓包,分析整个连接的建立过程:

从抓包结果可以看到,MySQL 的通信协议基于 TCP,并且是二进制协议,而不是类似 HTTP 的文本协议。连接建立过程可以拆成三步:
- 第 1 步:通过三次握手建立 TCP 连接;
- 第 2 步:服务器向客户端下发「握手信息」,客户端响应该握手消息;
- 第 3 步:客户端发送认证包,验证用户身份;验证通过后,服务器返回 OK 响应,之后才开始执行命令。
用户验证通过后,还会进行连接变量设置,比如字符集、是否自动提交事务等,期间会有多次数据交互。完成这些步骤后,才会执行真正的查询和更新操作。
本次测试只用 5 行代码建立连接,随后没有通过该连接执行任何操作。程序结束后,连接不是通过 Connection.close() 关闭,而是随着进程终止被异常断开,所以最后出现了 TCP 的 RST 报文。由于没有设置任何额外连接属性,设置属性阶段耗时可以认为是最少的;但驱动仍会默认设置字符集、事务自动提交等,具体取决于驱动实现。即便这样,统计信息显示:排除最后不需要服务器响应的 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 步:客户端发送关闭连接请求,无需等待服务端响应;
- 第 2 步:通过 TCP 四次挥手断开连接。
这次完整走完「建立连接 → 关闭连接」全过程,耗时:
747.284311 - 747.100954 = 0.183357s = 183.357ms
这里同样受网络状况影响,虽然比上面的 225ms 略少,但也接近 200ms 级别。
再做一个简单换算:假设一个日活 2 万的网站,每个用户每天只发 5 个请求,那么一天就有 10 万个请求。如果每次建连耗时按 150ms 保守计算,仅建立数据库连接一天就要耗费:
100000 * 150ms = 15000000ms = 15000s = 250min = 4.17h
也就是说,每天光建立数据库连接就可能花掉 4 个小时。所以数据库连接池不是“要不要用”,而是必须用。并且随着日活上升,单靠连接池也不够,还要结合缓存、SQL 预编译、负载均衡等手段。
本文的核心结论只有一个:数据库连接真的很耗时,不要频繁建立连接。
来源:blog.csdn.net/lmy86263/article/details/76165714