fiddler 链接mysql_数据库(MySql)连接详细讲解_开朗可燃冰Tto的博客-程序员宅基地

技术标签: fiddler 链接mysql  

前言

说到数据库连接,这个大家都很熟悉了。但是熟悉一般来自于下面三种情况

* 刚开始学编程的时候,老师就说用完的数据库连接一定要关闭,不然会有严重的后果。

* 编程一段时间后,大家都说要用连接池来优化数据库连接。

* 编程几年后,老大们说要考虑一台服务器mysql的并发连接数与负载等。

所以不停留在听说的层面,深入去学习与研究下mysql的连接机制与.net mysql驱动对连接的管理也挺有必要的。

本文会用到哪些工具

vs建立一个web项目,测试连接的建立与回收

navicate for mysql(可以看到mysql的连接数的实时监控)

nuget安装mysql.data.dll,.net mysql的驱动

**.net reflector* 反编译查看mysql驱动的源码

fiddler友情客串,测测并发

打开navicate for mysql->选择“工具”->服务器监控->勾选要监控的服务器

就可以看到这个服务器的实时连接情况,每隔5秒刷新一次。

每打开一个连接多一个,打开数据库的时候对一个,打开查询的时候也会多一个

eb5ed5c793c0c133937d7991919dbb62.png

如图的:1463 1465 1466就是刚才打开的。

一.先说说mysql的最大连接数

在navicate中查询:show variables like '%max_connections%';

可以看到默认的数值为:max_connections:151

为了便于测试我们修改my.ini文件中的max_connections参数,修改为10。一定要重启mysql服务才能生效

46e20d63b883320c29d6af29f90bded8.png

然后我们运行web项目,当打开页面的时候执行。注意这里注释了关闭连接语句:

9f51540be091c78d8a2b8e2a97ef2963.png

这时我们在chrome中访问页面,当打开第8个页面时出现:Too many connections的异常。

b90b0442fbca84900d26b6f10d69c719.png

为什么时第8个呢:因为之前说了打开数据库以及查询占了3个,所以8+3>10。自然就报mysql异常了。

我们看看服务器的监控:

61ed0141ca67026b085227336475ae12.png

都连接了2000多秒,还在一直连着,导致其他请求无法建立连接。这就是不释放连接的最直接的后果。

下面我们来手动结束那些没有被关闭的连接(右击连接->结束进程或者停止vs运行)。

接下来测试正常情况,取消连接关闭的注释

二.你关闭连接的时候,连接真的关闭了吗?

我们发现访问网页后,服务器中多了一个连接,进程id为1479。但是明明执行了connection.Close(),但结果好像不是我们预料的那样。

等待几十秒后发现随着访问的结束,这个连接的闲置时间为109秒没有被关闭掉。

69bbe2243eeccafdbbed2490e6b7af98.png

但当我们重新打开一个网页后,发现

6eb7f16dd097ac16cb96d803f95688fa.png

这个连接的闲置时间被重置了为0了。

这种现象跟mysql并没有太多原因,这是由mysql 的.net驱动控制的。当我们调用connection.Close()时,与mysql建立的socket连接被没有真正的关闭掉,而是被保留并置为空闲状态。

当新的请求连接过来后,会直接使用这个连接而不会建立新的socket连接。这是mysql驱动自带的连接池功能,来优化性能与资源。

我们来翻下mysql.data的源代码:

808fb51b1ad06419b48bf88205cdfbab.png

大部分情况下我们调用connection.Close()只是调用:this.SetState(ConnectionState.Close,true),改变一下连接的状态而已。并非真的关闭

真正的关闭时调用CloseFully()

5a841b47fd25645cfe1a5ab39a1626c6.png

mysql驱动申请的连接真正关闭是通过超时实现的。经过测试如果闲置300秒左右,这个连接就会被彻底关闭了

所以交互流程图是这样的:

6bf1efe494fe9e34499d824a22a3d548.png

三.断网了怎么办?

正常情况下自然是好,但是如果:

c1b3553a0b90daf643a08ffad5c30605.png

这时候出现的状况就比未手动关闭数据库连接还要严重,程序已经失去控制权了。会出现一批处于空闲中的数据库连接无法被正常释放掉。如果网络时好时坏,就有可能是一批接一批的。

所以mysql服务内部也有一个超时机制,当一个socket连接长期空闲的时候mysql服务端会强制关闭这个连接。如果等mysql的超时机制来处理的问题,

超时时间通过:show global variables like '%timeout%';

838f8e4fea397b8da3d8bc0912664479.png

如上图所示的wait_timeout就是控制等待空闲超时的参数,默认为28800秒也就是8小时

四.连接符中配置的Min Pool Size=?;Max Pool Size=?;驱动是如何管理的?

通常在配置连接字符串的使用连接池,如我们配置

var connection = new MySqlConnection(@"Data Source=121.40.64.127;port=3306; User ID=root;Password=root; database=spring;Persist Security Info=false; Connect Timeout=30;Min Pool Size=2;Max Pool Size=5;");

首先Min Pool Size=2;

运行项目后,会一次多出两个连接,如下图:

0d16605329444b7ceea26b53ee896e48.png

而且这两个连接只要iis没有回收,不会被销毁。

2afb8feecdcf4029eab4eae7387da6a5.png

任何请求过来后。只要这两个连接有空闲,就不会创建新的连接。

接着Max Pool Size=5;

如果Min Pool Size设置的数量不够用,也就是并发量大与2的时候,那么mysql驱动就会申请更多的连接。

我们来实际测试一下,使用fiddler我们来模拟下“瞬间的大量请求”:

打开fiddler->浏览器中请求网页->在filddler找到那个请求->按住shift->点击菜单中的Replay->输入50->点击ok

这样就会异步同时发出50个请求。

22ffeed3f7ae57761c7abed82019c7e4.png

0444a6e85749a184acab0c0b9170fe95.png

我们看下服务器的监控信息:

030fbe4c98834e82b91b914c9641ffaf.png

这时就会同时创建5个连接,因为2个不够 5个最大,所以只能创建5各连接供使用,后面的请求只能等其他请求释放连接以后才能进入处理。

如果你在连接关闭前设置:Thread.Sleep(5000),让连接延迟5秒再关闭。就能明显的感觉到大量数据库请求阻塞,因为没有额外的连接来处理请求了。

那是不是实际场景中,之前讲的max_connections与Max Pool Size都设置最大好了?

当然不是,服务器的性能有限啊。你设置最大,高并发的时候连接限制倒是没有,但整个服务器估计就挂了。

继续刚才的Max Pool Size,申请的五个连接,如果闲置300秒左右。有3个会被回收掉,只会保留Min Pool Size生成的2个。请看截图

541aa9a896624e8d7fd9e82e4fba575d.png

也就是连接符中设置的Min Pool Size会永久的生成两个连接在那里,不会被关闭。Max Pool Size只在Min Pool Size不够的时候生成,用完(闲置超时后)会被关闭掉。

程序中无论多少并发请求,mysql驱动提供给当前应用的连接数都不会超过Max Pool Size。这样看起来Max Pool Size也有保护服务器不被拖垮的作用

未完待续……

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30489285/article/details/113565355

智能推荐

Python配置Qt Designer与PyUIC_热心市民付先生的博客-程序员宅基地_python pyuic

Python配置Qt Designer与PyUIC安装pyqt相关包pip install pyqtpip install pyqt5-toolsPyCharm中选择相应的python解释器3. 添加外部工具名称填写自己方便易记得即可,我的名称添加为QTDesigner程序选择designer.exe,位置为当前解释器路径下的Lib\site-packages\pyqt5-tools\designer.exe工作目录为当前项目文件的目录添加选择完毕界面为:确定即可,再次

关于WebSocket_彪彪_的博客-程序员宅基地

原文链接:https://www.liaoxuefeng.com/wiki/1022910821149312/1103303693824096WebSocket是HTML5新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器可以在任意时刻发送消息给浏览器。为什么传统的HTTP协议不能做到WebSocket实现的功能?这是因为HTTP协议是一个请求-响应协议,...

FineUI初学手册_star_2008_的博客-程序员宅基地

女朋友鄙视我原创少...1.下载 进入官方论坛:http://www.fineui.com/bbs/要用到下载源代码和空项目下载http://fineui.codeplex.com/http://fineui.com/bbs/forum.php?mod=viewthread&tid=2123源代码直接下载,注意FineUI版本空项目里下载 对应版本的空项

NSStringDrawingOptions_yinachong的博客-程序员宅基地

NSStringDrawingTruncatesLastVisibleLine:如果文本内容超出指定的矩形限制,文本将被截去并在最后一个字符后加上省略号。如果没有指定NSStringDrawingUsesLineFragmentOrigin选项,则该选项被忽略。NSStringDrawingUsesLineFragmentOrigin:绘制文本时使用 line fragement or

条件注解@ConditionalOnBean失效原因_zhm_sky的博客-程序员宅基地_conditionalonbean不生效

测试环境(配置类)@Import({User.class,Pet.class})@Configuration(proxyBeanMethods = true)public class MyConfig { @Bean @ConditionalOnBean(name = "cat") public User user(){ return new User("航书", 12); } @Bean("cat") public

一重指针、二重指针做函数参数的深刻分析(虽然很基础,但要深刻理解)_ShenHang_的博客-程序员宅基地

一重指针做函数参数#include<iostream>using namespace std;void change(int *p){ *p = 20; p++; cout << p << endl;}int main() { int a = 10; change(&a); cout << &a <&lt...

随便推点

vassist的安装_kgduu的博客-程序员宅基地

在网上下载vassist安装压缩文件。1、运行VA_X_Setup

全方位讲解VoIP 的原理及技术知识_demon_evil的博客-程序员宅基地_voip工作原理

通过因特网进行语音通信是一个非常复杂的系统工程,其应用面很广,因此涉及的技术也特别多,其中最根本的技术是VoIP (Voice over IP)技术,可以说,因特网语音通信是VoIP技术的一个最典型的、也是最有前景的应用领域。因此在讨论用因特网进行语音通信之前,有必要首先分析VoIP的基本原理,以及VoIP中的相关技术问题。一、VoIP的基本传输过程传统的电话网是以电路交换方式传输语音,所要求的传

安卓设备抓包_Japher的博客-程序员宅基地

命令: adb shell su mount -o remount rw(空格)/  /data/local/tcpdump -p -vv -s 0 -w /sdcard/capture.pcap   

oracle设置core文件大小,Linux的Core文件设置与调试_李daxin的博客-程序员宅基地

一、运行时错误任何人写程序都会出错,正如《C++编程规范》所说,真正可怕的错误不是编译时的错误,而是运行时错误。有的程序可以通过编译, 但在运行时会出现Segment fault(段错误)这通常都是指针错误(一般就是空指针)引起的,或者访问了不能访问的内存(数组越界,系统保护)二、core文件我们不可能用GDB一句一句的去找,真正的英雄都善于使用手中的武器。这就是core file所谓core,就...

redis客户端连接遇到的坑,记录一下_choujulong7459的博客-程序员宅基地

期间出现的错误如下:1.connect timeout2.connect refused3.遗失对主机的连接denied redis is running in protected mode。。。。。。总结处理这些报错的步骤:1.关闭centos防火墙2.修改redis.conf文...