前言

说到数据库连接,这个大家都很熟悉了。但是熟悉一般来自于下面三种情况
* 刚开始学编程的时候,老师就说用完的数据库连接一定要关闭,不然会有严重的后果。
* 编程一段时间后,大家都说要用连接池来优化数据库连接。
* 编程几年后,老大们说要考虑一台服务器mysql的并发连接数与负载等。
所以不停留在听说的层面,深入去学习与研究下mysql的连接机制与.net mysql驱动对连接的管理也挺有必要的。

本文会用到哪些工具

  • vs建立一个web项目,测试连接的建立与回收
  • navicate for mysql(可以看到mysql的连接数的实时监控)
  • nuget安装mysql.data.dll,.net mysql的驱动
  • **.net reflector* 反编译查看mysql驱动的源码
  • fiddler友情客串,测测并发

打开navicate for mysql->选择“工具”->服务器监控->勾选要监控的服务器
就可以看到这个服务器的实时连接情况,每隔5秒刷新一次。
每打开一个连接多一个,打开数据库的时候对一个,打开查询的时候也会多一个

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


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

在navicate中查询:show variables like '%max_connections%';
可以看到默认的数值为:max_connections:151

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


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

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

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

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

下面我们来手动结束那些没有被关闭的连接(右击连接->结束进程或者停止vs运行)。
接下来测试正常情况,取消连接关闭的注释

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

我们发现访问网页后,服务器中多了一个连接,进程id为1479。但是明明执行了connection.Close(),但结果好像不是我们预料的那样。
等待几十秒后发现随着访问的结束,这个连接的闲置时间为109秒没有被关闭掉。

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

这个连接的闲置时间被重置了为0了。
这种现象跟mysql并没有太多原因,这是由mysql 的.net驱动控制的。当我们调用connection.Close()时,与mysql建立的socket连接被没有真正的关闭掉,而是被保留并置为空闲状态。
当新的请求连接过来后,会直接使用这个连接而不会建立新的socket连接。这是mysql驱动自带的连接池功能,来优化性能与资源。
我们来翻下mysql.data的源代码:

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

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

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

三.断网了怎么办?

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

这时候出现的状况就比未手动关闭数据库连接还要严重,程序已经失去控制权了。会出现一批处于空闲中的数据库连接无法被正常释放掉。如果网络时好时坏,就有可能是一批接一批的。
所以mysql服务内部也有一个超时机制,当一个socket连接长期空闲的时候mysql服务端会强制关闭这个连接。如果等mysql的超时机制来处理的问题,
超时时间通过:show global variables like '%timeout%';

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

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

通常在配置连接字符串的使用连接池,如我们配置
var connection = new MySqlConnection(@"Data Source=*;port=3306; User ID=*;Password=*; database=spring;Persist Security Info=false; Connect Timeout=30;Min Pool Size=2;Max Pool Size=5;");

首先Min Pool Size=2;

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

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

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

接着Max Pool Size=5;

如果Min Pool Size设置的数量不够用,也就是并发量大与2的时候,那么mysql驱动就会申请更多的连接。
我们来实际测试一下,使用fiddler我们来模拟下“瞬间的大量请求”:

打开fiddler->浏览器中请求网页->在filddler找到那个请求->按住shift->点击菜单中的Replay->输入50->点击ok
这样就会异步同时发出50个请求。


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

这时就会同时创建5个连接,因为2个不够 5个最大,所以只能创建5各连接供使用,后面的请求只能等其他请求释放连接以后才能进入处理。
如果你在连接关闭前设置:Thread.Sleep(5000),让连接延迟5秒再关闭。就能明显的感觉到大量数据库请求阻塞,因为没有额外的连接来处理请求了。
那是不是实际场景中,之前讲的max_connectionsMax Pool Size都设置最大好了?
当然不是,服务器的性能有限啊。你设置最大,高并发的时候连接限制倒是没有,但整个服务器估计就挂了。
继续刚才的Max Pool Size,申请的五个连接,如果闲置300秒左右。有3个会被回收掉,只会保留Min Pool Size生成的2个。请看截图

也就是连接符中设置的Min Pool Size会永久的生成两个连接在那里,不会被关闭。Max Pool Size只在Min Pool Size不够的时候生成,用完(闲置超时后)会被关闭掉
程序中无论多少并发请求,mysql驱动提供给当前应用的连接数都不会超过Max Pool Size。这样看起来Max Pool Size也有保护服务器不被拖垮的作用

未完待续……

聊聊数据库(MySql)连接吧,你真的清楚吗?的更多相关文章

  1. 关于Django数据库mysql连接错误问题Connection to api@localhost failed. [08001] Could not create connection to d

    Connection to api@localhost failed. [08001] Could not create connection to d 错误类型 django连接mysql数据库错误 ...

  2. JAVAWEB和数据库 Mysql连接不上的原因及解决方案

    有可能是安装了phpstudy或者wampserver这类自带mysql的web集成环境, 在关闭集成环境时误关了相对应的mysql服务,所以我们需要手动启动服务. 启动mysql的命令: net s ...

  3. JNDI实现服务器(tomcat)与数据库(mysql)连接的数据源配置以及获取连接的java代码

    ->首先将mysql的jar包导入到tomcat/lib文件夹下 ->然后在tomcat/conf/context.xml文件中配置以下内容 <Resource name=" ...

  4. Swift3.0服务端开发(四) MySQL数据库的连接与操作

    本篇博客我们来聊聊MySQL数据库的连接与操作.如果你本地没有MySQL数据库的话,需要你先安装MySQL数据库.在Mac OS中使用brew包管理器进行MySQL的安装是及其方便的.安装MySQL的 ...

  5. JAVA与数据库MySQL相连接

    JDBC(Java数据库连接体系结构): 是Java实现数据库访问的应用程序编程接口,主要功能是管理存放在数据库中的数据.通过接口对象,应用程序可以完成与数据库的连接,执行SQL语句,从数据库中获取结 ...

  6. Java分别与MySQL、Oracle、SQL Server数据库建立连接

    1.与MySQL连接 jar包下载地址: Class.forName("com.mysql.jdbc.Driver");//加载数据库驱动(MySQL的jar包) String u ...

  7. MySQL数据库远程连接

    12.00 MySQL数据库远程连接 参考: http://www.jb51.net/article/24508.htm http://www.linuxdiyf.com/viewarticle.ph ...

  8. PHP MYSQL 数据库配置连接

    //配置文件 Config.php // 默认使用数据库配置 ***************************************** $Config['ConnectTag'] = 'de ...

  9. Java对MySQL数据库进行连接、查询和修改【转载】

    一般过程: (1) 调用Class.forName()方法加载驱动程序. (2) 调用DriverManager对象的getConnection()方法,获得一个Connection对象. (3) 创 ...

随机推荐

  1. ubuntu安装wine之后进不了系统

    以前曾经装过一次wine,安装的时候没碰到什么问题,但卸载的时候却出问题了,把我nouvean显卡给删除了. 自然,我下一次启动的时候就进不了桌面了.所以我得重装一次,那一次重装的是整个系统! 今天突 ...

  2. 激活windows server 2012 R2的方法

    首先登陆dreamspark 注册一个账号https://www.dreamspark.com/Account/SignIn.aspx, 点击创建账户,信息可以完全瞎编,邮箱不存在也可以.然后使用“我 ...

  3. android的版本控制

    在一个团队项目中,项目的版本控制,一方面促进团队的协同能力,另一方面提高项目的进度 即使一个人的项目也最好使用SVN这样的版本控制,可以清楚的知道自己的修改的代码,和项目进度等.合理的托管,也让优秀的 ...

  4. Re-installation failed due to different application signatures.的解决方案

    有时在安装不同版本apk文件时会出现Re-installation failed due to different application signatures.这样的提示 主要原因是安装的apk程序 ...

  5. Git工作流:中心工作流(翻译)

    使用Git作为版本控制器,有众多可能的工作流(Workflow),这使得我们这些新鸟不知道在实际工作中不知道该选择哪种工作流.这里我们对最常见的Git工作流做一个对比,为企业团队提供一个参考. 正如你 ...

  6. Asp.net MVC4.0(net4.5) 部署到window server 2003上的解决方案

    Asp.net MVC4.0(net4.5) 部署到window server 2003上的解决方案 最近做了一个Web项目,也没多想就用了Asp.net MVC4.0 ,MVC4.0默认的目标fra ...

  7. C#事件与委托的区别

    C#事件与委托的区别 1. 委托 事件是利用委托来定义的,因此先解释委托.委托是一个类,它与其他类如int,string等没有本质区别,int代表的是所有的整形,而string代表的是字符串,委托则代 ...

  8. Mac OS X安装之硬盘和光盘引导总结

    继上一篇虚拟机环境下的安装,这篇文档主要描述硬盘和光盘引导安装Mac OS X,并可实现多操作系统. 硬盘安装: 首先介绍下硬盘安装需要用到的软件. Java虚拟机.作为HFSExplorer的运行前 ...

  9. [转]OpenSolaris 2009.06, dev setup

    Source:http://seriouswebapps.com/opensolaris-200906-dev-setup 1. Snapshot the root zfs pool This all ...

  10. IIS配置PHP环境

    IIS配置PHP环境(快速最新版)(转载+自创) (参考转载的) 我们知道php配置有几种: 1.CGI方式加载PHP环境,通常就是IIS里面配置解释器为php.exe,早期比较常见,目前使用较少.  ...