首页 > 数据库 >为什么数据库连接很消耗资源?

为什么数据库连接很消耗资源?

时间:2024-03-15 09:00:52浏览次数:28  
标签:String 建立 数据库 消耗 TCP 连接 客户端

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

本文主要想探究一下连接数据库的细节,尤其是在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的预编译
  • 负载均衡
  • ……

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

标签:String,建立,数据库,消耗,TCP,连接,客户端
From: https://www.cnblogs.com/shujuyr/p/18074431

相关文章

  • 【PG】Ora2pg 数据库对象迁移顺序
    在将数据库对象从Oracle迁移到PostgreSQL时,以下是一个常见的迁移顺序建议:表:首先迁移表的结构和数据,因为其他对象(如索引、触发器和函数)可能依赖于表的存在。索引:迁移表之后,迁移索引。在PostgreSQL中创建与Oracle索引相对应的索引。触发器:迁移触发器。在PostgreSQL中创建与O......
  • 【PG】创建数据库,账户以及schema
    #!/bin/bash#Checkifrunningasthepostgresuserif[["$USER"!="postgres"]];thenecho"Error:Thisscriptmustberunasthepostgresuser."exit1fi#Checkinputparametersif[$#-ne3];thenecho"......
  • 数据库不应放在容器中?- B站Kubernetes有状态服务实践(Elasticsearch/Clickhouse)
    本期作者前言云原生时代下,Kubernetes已成为容器技术的事实标准, 使得基础设施领域应用下自动化运维管理与编排成为可能。对于无状态服务而言, 业界早已落地数套成熟且较完美的解决方案。可对于有状态的服务, 方案的复杂度就以几何倍数增长, 例如分布式应用多个实例间的依......
  • 【SpringBoot】自定义工具类实现Excel数据新建表存入MySQL数据库
    ......
  • 基于大模型和向量数据库的 RAG 示例
    1        RAG介绍RAG是一种先进的自然语言处理方法,它结合了信息检索和文本生成技术,用于提高问答系统、聊天机器人等应用的性能。2        RAG的工作流程文档加载(DocumentLoading)从各种来源加载大量文档数据。这些文档将作为知识库,用于后续的信息检索......
  • 【鸿蒙ArkTs】沙箱内sqlite数据库db文件导入导出
    1.数据库在沙箱内位置沙箱文件目录官方文档说明获取数据库路径:let数据库路径='/data/storage/el2/database/entry/rdb/Mydata.db'2.数据库临时文件找到了数据库db文件,只导出这个db文件是没有用的。因为还有db-wal这个临时文件。系统并没有把数据全部写入db,甚至重启手机......
  • Qt TCP通信客户端断开连接有哪些方法
    在QT中,可以使用以下方法来处理TCP通信客户端断开连接的情况:使用QAbstractSocket::disconnected信号:当客户端与服务器断开连接时,该信号会被触发。你可以连接这个信号到一个槽函数,在槽函数中处理断开连接的逻辑。QObject::connect(socket,&QTcpSocket::disconnected,this,&You......
  • gorm使用事务并发情况下切有最大mysql连接数限制的情况下的BUG,踩坑了
    现象服务器pprof中的goroutines很多,无法释放,肯定是异常.代码//收到请求上个赛季个人秘境赛季排行func(this*MsgProc)MsgProc_PersonSecretLastRankReq(msg*protoMsg.PersonSecretLastRankReq){ global.GetSrvInst().GetThreadGo().Go(func(ctxcontext.Context)......
  • 高并发下如何解决数据库性能瓶颈问题
    在高并发场景下,数据库往往是性能瓶颈的一个重要因素。以下是一些常用的方法来解决数据库性能瓶颈问题:数据库优化:对数据库进行性能调优,包括索引优化、查询优化、表结构设计优化等。使用合适的索引可以加速查询操作,同时注意避免过多索引导致性能下降。优化查询语句,避免不必要的......
  • mybatis oracle数据库批量插入数据,忽略主键重复
    dao方法IntegerinsertPackagesNew(@Param("list")List<InfCollectpackage>list);mapper.xml<insertid="insertPackagesNew"parameterType="java.util.List">MERGEINTOINF_COLLECTPACKAGEAUSING(&......