很好奇为什么PHP没有数据库连接池,就翻了下PHP中mysql模块的源码,发现mysql_pconnect使用zend引擎的函数pemalloc()将数据库连接资源存在了全局内存中。这样看来,mysql_pconnect的效率应该很高,但是为什么很少有人用呢?

1.正常情况下当一个链接断开,你锁的表也会跟着解锁。但是长链接却永远不断开的,所以一个表万一一不小心锁了就一直锁着,除非你等着链接超时或者杀掉进程。同样的锁的问题也会在处理事务的时候发生。

2.正常情况下当一个链接断开,临时表也会被删除。但是由于长链接并不断开,临时表就变得不那么临时了。所以,临时表如果在完成业务后没有被删除,将会继续存在,提供给复用这个长链接的客户端使用。

3.如果PHP和mysql在同一台服务器上或者同一个局域网内,链接的时间是可以忽略不计的,所以用长链接不会得到任何益处。

4.Apache不能很好的处理长链接。当Apache接收到一个新的客户端的请求,它并不会使用一个已经拥有可用长链接的子进程,而是生成一个新的子进程,这个子进程会打开一个新的数据库连接。这就造成空闲的额外进程,资源的浪费,并且,当达到最大连接数时还会导致错误。得不偿失啊~

看看其他人怎么说的?

有一个哥们说:(这哥们是老外,我直接翻译了)

一般情况下,你是不会想用mysql_pconnect的。这个函数是为了连接数据库高开销的场景设计的。典型的Mysql / Apache / PHP 场景中,Apache会创建很多空闲的子进程来等待web请求。这里的每个子进程都会打开并维持一个独立的Mysql链接。所以,如果Mysql Server限制50个链接,而Apache有大于50个的子进程在跑,每个子进程都会建立一个独立的Mysql链接,哪怕他们是空闲的(空闲的httpd子进程不跟其它进程共享Mysql链接)。因此,即使你只有很少几个需要链接数据库的页面跑在一个繁忙的站点上,也会很快用光连接数,而实际上并没有全部被利用上。

所以,用mysql_connect()链接Mysql吧,除非,每次建立连接都要花去大把的时间。

看看官方怎么说的:(地址:http://devzone.zend.com/node/view/id/686#fn1)

The mysql_pconnect() function was designed to provide a mechanism for reducing the cost of establishing and closing connections to the MySQL server. Unfortunately, due to an interaction between the architecture of the Apache server and the architecture of PHP, high traffic on a site that used pconnects could quickly clog up the MySQL server with many unused connections that could prevent many of the active connections from accessing the database.

翻译下:

mysql_pconnect()函数设计的目的是为了提供一种机制来减少与Mysql服务器建立/断开连接的开销。不幸的是,由于Apache服务器架构和PHP架构之间的相互作用,一个使用长链接的高流量的网站会因为很多没有使用的链接迅速堵塞Mysql服务器,并且导致活跃的链接无法访问数据库。

最后,俺们再看下手册上咋写的:

警告:在使用永久连接时还有一些特别的问题需要注意。例如在永久连接中使用数据表锁时,如果脚本不管什么原因无法释放该数据表锁,其随后使用相同连接的脚本将会被永久的阻塞,使得需要重新启动 httpd 服务或者数据库服务。另外,在使用事务处理时,如果脚本在事务阻塞产生前结束,则该阻塞也会影响到使用相同连接的下一个脚本。不管在什么情况下,都可以通过使用 register_shutdown_function() 函数来注册一个简单的清理函数来打开数据表锁,或者回滚事务。或者更好的处理方法,是不在使用数据表锁或者事务处理的脚本中使用永久连接,这可以从根本上解决这个问题(当然还可以在其它地方使用永久连接)。

好了,就写到这了。你还敢用mysql_pconnect()吗??