onlyliuxin / coding2017

216 stars 641 forks source link

为什么数据库连接很“昂贵"? #451

Open onlyliuxin opened 7 years ago

wubingyang commented 7 years ago

因为要创建Socket连接...如果只是单次简单查询时间远超过建立socket的话,,那么久很昂贵了

lanyuanxiaoyao commented 7 years ago

关于问题

关于这个问题,我是没有任何实践经验的,本着能答就答的原则,我是不能答这个问题的,但是刘老师推荐了这个问题,我就决定去找一下答案,权当一道面试题来对待了,毕竟造航母嘛,原理性的东西虽然都很难用上,但是知道多一些总是没有坏处的 第一眼见到这个问题的时候,我想到的就是数据库连接池,因为一直以来我对数据库连接池的印象就是——解决了创建数据库连接开销大的问题,不过就像线程池一样,数据库连接为什么开销大,这个问题倒是从来都没有想过,就像很多面试题一样,我也仅仅只是记住了答案,所以现在有了一个深究的机会整理我从网上搜集到的资料

数据库连接

我们都知道数据库连接创建的开销很大,但是数据库连接的原理是什么呢?到底是哪个环节导致了开销的出现?我还有点懵逼,所以搞懂数据库连接是个重要的问题。 一个数据库连接的流程是这样的:

  1. 应用程序的数据访问层请求DataSource来获取一个数据库连接。
  2. DataSource使用数据库驱动来打开一个数据库连接。
  3. 创建数据库连接,同时打开了一个TCP socket。
  4. 应用程序进行数据库的读写。
  5. 连接已经不再需要了,因此关闭它。
  6. 关闭socket。

我们有一个示意图可以看:

开销分析

连接层面

从前面的示意图可以看出,基本步骤只有6个,而且我们知道,一些基本的步骤之下往往有很多的基础操作作支撑,每一个都可能成为开销的来源,尤其是在建立TCP连接的时候,需要经过多层的网络协议进行协助,此外还需要:

  1. 校验用户的身份证书
  2. 在数据库驱动期望的代码页设置和数据库可用的代码页设置之间进行协商
  3. 获取数据库版本信息
  4. 确定用于通信的最理想的数据库协议包大小
  5. 设置会话设置

这些额外的流程其实是在保证数据库最重要的两个点:安全稳定。如果我们需要一个安全的数据库,那么首先我们就要校验操作对象的身份,是否拥有数据库的操作权限,然后在连接中保持用户的状态权限,这就需要操作服务器的session,然后和发起连接的主机进行数据传递参数的适配,以保证返回正确的数据。

存储层面

第一点是我们知道即使是一个连接的操作,数据库也是要访问相应的表来确定访问对象的,这就涉及到了查表的操作,而大型数据库的表往往不会完全存在缓存里,这就需要到存储结构中区查询,也就是会产生I/O操作,而I/O操作也是拉慢速度的一大根源。 第二点是当我们数据库的连接比较多的时候,存在缓存中的页就会很有限,从而使数据库连接的访问呢发生不命中,这时候数据库往往需要到磁盘上去把对应的数据调度出来,供连接使用,I/O操作的缓慢就很明显了。

总结

数据库连接的开销在于多层的调用,以及一些耗时操作(I/O,TCP连接),为了保证数据库的安全,各种校验方式也在不同程度上带来了开销,所以说数据库连接的花费相当“昂贵”。
从另一个方面想,我们把线程池和数据库连接池放在一起对比的时候,常常会误认为线程和连接会是同一个形式的东西,但是事实上并不是这样,线程是由计算机硬件来实现的分时调度的一个逻辑概念,是接近系统底层的,而数据库连接是基于TCP连接的一个应用层的由数据库应用实现的一个协议,或者说是一个功能,和我们寻常的网络传输,比如聊QQ,是同样性质的东西,所以其中建立一个数据库连接是要设计OSI应用层以下各个层次的配合才能实现的,网络传输的建立和磁盘I/O的速率限制相加,再加上数据库应用本身的身份校验和数据校验,就让一个数据库连接变得十分消耗。

参考文章

Wrecksoul commented 7 years ago

面试的话肯定要几句话说到重点啊喂。。。

我觉得“昂贵”之处在于使用的是tcp/ip连接,这种连接的建立非常耗时而且需要发送数据包进行互相确认,而,相比于一次简单查询只需要发送一次而且一般就一个包耗费的时间和资源来说相当昂贵了

orajavac commented 7 years ago

从数据库角度来说,就拿oracle来讲,首先要分配进程,一个进程对应一个客户端,既然有进程就要为进程分配内存,而且当连接数据库时候,数据库内部要对用户/密码,权限做验证,看似操作简单,但是如果多客户端同时进行连接,不一会就断掉,我们称为短连接,对数据库来讲非常耗资源,数据库要频繁分配进程、回收进程。对于网络连接这块,推荐:<<网络是怎样连接的>>书,写的很详细

liubin-vip commented 7 years ago

1.建立网络连接 2.建立各种缓冲区