深入探讨: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 相关文章推荐
不用数据库的多用户文件自由上传投票系统(3)
Oct 09 PHP
PHP面向对象三大特点学习(充分理解抽象、封装、继承、多态)
May 07 PHP
PHP常用的文件操作函数经典收藏
Apr 02 PHP
Mysql中分页查询的两个解决方法比较
May 02 PHP
LotusPhp笔记之:Cookie组件的使用详解
May 06 PHP
php格式输出文件var_export函数实例
Nov 15 PHP
PHP的几个常用加密函数
Feb 03 PHP
Yii隐藏URL中index.php的方法
Jul 12 PHP
php rmdir使用递归函数删除非空目录实例详解
Oct 20 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
Aug 30 PHP
PHP实现求连续子数组最大和问题2种解决方法
Dec 26 PHP
imagettftext() 失效,不起作用
Mar 09 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
MySQL授权问题总结
2007/05/06 PHP
2014过年倒计时示例
2014/01/31 PHP
使用PHPExcel实现数据批量导出为excel表格的方法(必看)
2017/06/09 PHP
Yii框架ACF(accessController)简单权限控制操作示例
2019/04/26 PHP
JQUERY THICKBOX弹出层插件
2008/08/30 Javascript
javascript 文本框水印/占位符(watermark/placeholder)实现方法
2012/01/15 Javascript
javascript:void(0)使用探讨
2013/08/27 Javascript
Jquery validation remote 验证的缓存问题解决方法
2014/03/25 Javascript
js父页面与子页面不同时显示的方法
2014/10/16 Javascript
javascript中innerText和innerHTML属性用法实例分析
2015/05/13 Javascript
js实现拖拽效果(构造函数)
2015/12/14 Javascript
JavaScript中setTimeout的那些事儿
2016/11/14 Javascript
JS DOMReady事件的六种实现方法总结
2016/11/23 Javascript
vue.js绑定事件监听器示例【基于v-on事件绑定】
2018/07/07 Javascript
js for终止循环 跳出多层循环
2018/10/04 Javascript
JavaScript中引用vs复制示例详析
2018/12/06 Javascript
Openlayers学习之地图比例尺控件
2020/09/28 Javascript
Vue-Ant Design Vue-普通及自定义校验实例
2020/10/24 Javascript
[05:09]第二届DOTA2亚洲邀请赛决赛日比赛集锦:iG 3:0 OG夺冠
2017/04/05 DOTA
Python清空文件并替换内容的实例
2018/10/22 Python
python实现控制电脑鼠标和键盘,登录QQ的方法示例
2019/07/06 Python
使用Pandas对数据进行筛选和排序的实现
2019/07/29 Python
在Python中获取操作系统的进程信息
2019/08/27 Python
python获取Linux发行版名称
2019/08/30 Python
详解修改Anaconda中的Jupyter Notebook默认工作路径的三种方式
2021/01/24 Python
美国最大的家庭鞋类零售商之一:Shoe Carnival
2017/10/06 全球购物
菲律宾购物网站:Lazada菲律宾
2018/04/05 全球购物
NBA欧洲商店(英国):NBA Europe Store UK
2018/07/27 全球购物
时尚设计师手表:The Watch Cabin
2018/10/06 全球购物
电子商务网站的创业计划书
2014/01/05 职场文书
《邮票齿孔的故事》教学反思
2014/02/22 职场文书
硕士生工作推荐信
2014/03/07 职场文书
企业出纳岗位职责
2014/03/12 职场文书
《长征》教学反思
2014/04/27 职场文书
goland 清除所有的默认设置操作
2021/04/28 Golang
分享几个简单MySQL优化小妙招
2022/03/31 MySQL