深入探讨:PHP使用数据库永久连接方式操作MySQL的是与非


Posted in PHP onJune 05, 2013

PHP程序员应该都知道连接MySQL数据库可以使用mysql_pconnect(永久连接)函数,使用数据库永久连接可以提高效率,但是实际应用中数据库永久连接往往会导致出现一些问题,通常的表现就是在大访问量的网站上时常发生断断续续的无法连接数据库的情况,出现类似"Too many connections in ..."的错误提示信息,重新启动服务器又正常了,但过不了一会儿又出现同样的故障。对于这些问题的成因,恐怕就不是每个人都能说清楚的了,虽然PHP文档里有一些相关资料,但是解释的并不浅显易懂,这里我厚着脸皮试图做一个简单的讨论,所述观点不见得全都正确,欢迎大家反馈意见。

首先看看数据库永久连接的定义:
永久的数据库连接是指在脚本结束运行时不关闭的连接。当收到一个永久连接的请求时。PHP 将检查是否已经存在一个(前面已经开启的)相同的永久连接。如果存在,将直接使用这个连接;如果不存在,则建立一个新的连接。所谓“相同”的连接是指用相同的用户名和密码到相同主机的连接。

PHP使用永久连接方式操作MySQL是有前提的:就是PHP必须安装为多线程或多进程Web服务器的插件或模块。最常见的形式是把PHP用作多进程Apache服务器的一个模块。对于一个多进程的服务器,其典型特征是有一个父进程和一组子进程协调运行,其中实际生成Web页面的是子进程。每当客户端向父进程提出请求时,该请求会被传递给还没有被其它的客户端请求占用的子进程。这也就是说当相同的客户端第二次向服务端提出请求时,它将有可能被一个不同的子进程来处理。在开启了一个永久连接后,所有不同子进程请求SQL服务的后继页面都能够重新使用这个已经建立的 SQL服务器连接。它使得每个子进程在其生命周期中只做一次连接操作,而非每次在处理一个页面时都要向 SQL 服务器提出连接请求。每个子进程将对服务器建立各自独立的永久连接。PHP本身并没有数据库连接池的概念,但是Apache有进程池的概念, 一个Apache子进程结束后会被放回进程池, 这也就使得用mysql_pconnect打开的的那个mysql连接资源可以不被释放,而是依附在相应的Apache子进程上保存到了进程池中。于是在下一个连接请求时它就可以被复用。一切看起来似乎都很正常,但是在Apache并发访问量大的时候,如果使用mysql_pconnect,会由于之前的 Apache子进程占用的MySQL连接没有close, 很快使MySQL达到最大连接数,使得之后的请求可能得不到响应。

上面的部分文字是摘抄自PHP文档,看起来可能还是有些文绉绉的不好理解,那么我就用大白话再举一个例子来说明问题:

假设Apache配置最大连接数为1000,MySQL配置最大连接数为100,当Apache服务器接到200个并发访问的时候,其中100个涉及到数据库访问,剩下的100个不涉及数据库访问,因为这个时候还不存在可用的数据库连接,所以这里面涉及到数据库访问的100个并发会同时产生100个数据库永久连接,达到了数据库最大连接数,当这些操作没有结束的时候,任何其他的连接都无法再获得数据库连接,当这些操作结束了,相应的连接会被放入进程池,此时Apache的进程池里就有了200个空闲的子进程,其中100个是带有数据库连接的,由于Apache会为访问请求随机的挑选空闲子进程,所以你得到的子进程很可能是不包含数据库连接的那100个中的一个,而数据库连接已经达到了最大值,你也不可能成功的建立新的数据库连接,唉,你便只好不停的刷新页面,哪个时候运气好,碰巧分配到了带有数据库连接的子进程,才能正常浏览页面。如果是大访问量的网站来说,任何时候都可能存在大量的并发,所以浏览者可能就会不停的发现无法连接数据库的现象了。

或许你会说,我们把Apache和MySQL的最大连接数调成一样大不就可以了么?是的,合理的调整这个最大连接数某种程度上会避免这个问题的发生,但是Apache和MySQL的负载能力是不同的,如果按照Apache的负载能力来设置,对于MySQL来说,这个最大连接数就偏大,会产生大量的 MySQL数据库永久连接,打个比方,就好像和平时代还要养活一个几百万的军队一样,其开销得不偿失;而如果按照Mysql的负载能力设置,对于 Apache来说,这个最大连接数就偏小,有点杀鸡牛刀的感觉,无法发挥Apache的最大效率。

所以按照PHP手册上的介绍,只适合在并发访问不大的网站上使用数据库永久连接,但对于一个并发访问不大的网站来说,使用数据库永久连接带来的效率提高似乎没有太大的意义,从这个角度上来看,我觉得PHP中的数据库永久连接基本上是一个鸡肋的角色,如果你一定要使用数据库连接池的概念,可以尝试一下sqlrelay或者Apache本身提供的mod_dbd,说不定会有惊喜。

PHP 相关文章推荐
PHP.MVC的模板标签系统(四)
Sep 05 PHP
PHP中将数组转成XML格式的实现代码
Aug 08 PHP
php 操作数组(合并,拆分,追加,查找,删除等)
Jul 20 PHP
PHP读取CURL模拟登录时生成Cookie文件的方法
Nov 04 PHP
PHP使用array_multisort对多个数组或多维数组进行排序
Dec 16 PHP
php带抄送和密件抄送的邮件发送方法
Mar 20 PHP
apache和PHP如何整合在一起
Oct 12 PHP
Yii2隐藏frontend/web和backend/web的方法
Dec 12 PHP
safari下载文件自动加了html后缀问题
Nov 09 PHP
PHP设计模式之观察者模式定义与用法分析
Apr 04 PHP
Yii2框架中一些折磨人的坑
Dec 15 PHP
php 输出缓冲 Output Control用法实例详解
Mar 03 PHP
深入理解用mysql_fetch_row()以数组的形式返回查询结果
Jun 05 #PHP
fetchAll()与mysql_fetch_array()的区别详解
Jun 05 #PHP
用mysql_fetch_array()获取当前行数据的方法详解
Jun 05 #PHP
深入分析使用mysql_fetch_object()以对象的形式返回查询结果
Jun 05 #PHP
深入mysql_fetch_row()与mysql_fetch_array()的区别详解
Jun 05 #PHP
浅谈php serialize()与unserialize()的用法
Jun 05 #PHP
基于php 随机数的深入理解
Jun 05 #PHP
You might like
在PHP3中实现SESSION的功能(三)
2006/10/09 PHP
盘点PHP和ASP.NET的10大对比!
2015/12/24 PHP
浅析Yii2 GridView 日期格式化并实现日期可搜索教程
2016/04/22 PHP
Ajax提交表单时验证码自动验证 php后端验证码检测
2016/07/20 PHP
Laravel推荐使用的十个辅助函数
2019/05/10 PHP
PHP进阶学习之垃圾回收机制详解
2019/06/18 PHP
初学Javascript的一些总结
2008/11/03 Javascript
Moment.js 不容错过的超棒Javascript日期处理类库
2012/04/15 Javascript
javascript中通过arguments参数伪装方法重载
2014/10/08 Javascript
js时间日期格式化封装函数
2014/12/02 Javascript
获取阴历(农历)和当前日期的js代码
2016/02/15 Javascript
基于js里调用函数时,函数名带括号和不带括号的区别
2016/07/28 Javascript
JS 动态加载js文件和css文件 同步/异步的两种简单方式
2016/09/23 Javascript
jquery处理checkbox(复选框)是否被选中实例代码
2017/06/12 jQuery
利用 spin.js 生成等待效果(js 等待效果)
2017/06/25 Javascript
父组件中vuex方法更新state子组件不能及时更新并渲染的完美解决方法
2018/04/25 Javascript
js合并两个数组生成合并后的key:value数组
2018/05/09 Javascript
深入浅析JS中的严格模式
2018/06/04 Javascript
React中嵌套组件与被嵌套组件的通信过程
2018/07/11 Javascript
30分钟精通React今年最劲爆的新特性——React Hooks
2019/03/11 Javascript
微信小程序云开发详细教程
2019/05/16 Javascript
解决Vue的项目使用Element ui 走马灯无法实现的问题
2020/08/03 Javascript
[03:48]DOTA2完美大师赛主赛事第二日精彩集锦
2017/11/24 DOTA
[58:54]EG vs RNG 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
[06:57]DOTA2-DPC中国联赛 正赛 Ehome vs PSG.LGD 选手采访
2021/03/11 DOTA
python插入数据到列表的方法
2015/04/30 Python
Python 基于Twisted框架的文件夹网络传输源码
2016/08/28 Python
centos6.5安装python3.7.1之后无法使用pip的解决方案
2019/02/14 Python
python如何实现数据的线性拟合
2019/07/19 Python
Django ORM 聚合查询和分组查询实现详解
2019/08/09 Python
python Manager 之dict KeyError问题的解决
2019/12/21 Python
英国领先的男士服装和时尚零售商:Burton
2017/01/09 全球购物
ghd法国官方网站:英国最受欢迎的美发工具品牌
2019/04/18 全球购物
会计工作心得体会
2014/01/13 职场文书
机械工程及自动化专业求职信
2014/09/03 职场文书
幼儿园推普周活动总结
2015/05/07 职场文书