为什么数据库连接很消耗资源 转
开发应用程序久了,总想刨根问底,尤其对一些有公共答案的问题。大家都能解释,但是追根究底,都解释不清。凡是都有为什么,而且用数字说明问题是最直观的。
本文主要想探究一下连接数据库的细节,尤其是在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
的文本协议,其中建立连接的过程具体如下:
- 第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
的预编译- 负载均衡
- ……
当然这不是本文的主要内容,本文想要阐述的核心思想只有一个,数据库连接真的很耗时,所以不要频繁的建立连接。
原文地址:https://www.cnblogs.com/php-linux/p/13308486.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- golang判断map中key是否存在的方法
- 迁移实战:一次AntDB(基于pgxl分布式架构的数据库)数据库迁移经验分享
- 看完这篇文章,99%的人都会使用Mysql Explain工具
- 浅析MySQL存储引擎序列属性
- 详述MySQL Using intersect交集算法
- 案例:强制开库遭遇ORA-16433的处理过程
- 叮~AutoML自动化机器学习入门指南,来了
- 注意:ORACLE 11G ADG RAC 这个情况下并不能高可用
- Nginx转发指向数据库端口并对外开放访问权限
- Python手写了 35 种可解释的特征工程方法
- Geant4--G4ParticleGun定义射线源的发射能谱
- Sony-PMCA-RE, 反向工程索尼PlayMemories相机应用
- 中标麒麟系统Your trial is EXPIRED and no VALID licens
- R初探
- 独家 | 在Python编程面试前需要学会的10个算法(附代码)