PHP数据库长连接mysql

  • 时间:
  • 浏览:0

echo "Apache守护进程池池号:".getmypid();

<?php

  2 wait_timeout        = 60

  浏览器是缘何知道需要重新进行TCP连接就还可以直接发送http请求呢?机会http返回头里就会带上Connection:keep-alive,Keep-alive:15两行,意思而是我让客户端浏览器明白,这次socket连接我这边还没关闭呢,你还可以在15内继续使用之类 连接,并发送http请求,于是乎浏览器就知道应该缘何做了。

...

<?php

if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) {

  +-----+------+-----------+------+--------+-----+------+-----------------+

zend_hash_find比较容易看明白,原型是zend_hash_find(hash表,key名,key长,value);机会找到,value需要值了。

Z_TYPE(new_le) = le_plink;

  以上的代码没啥好解释的,你还可以 们用浏览器浏览之类 页面,就看之类 ?就看一另一一八个 显眼的数字。一另一一八个 是MySQL守护进程池号,一另一一八个 是Apache守护进程池池号,好了,15秒后再刷新之类 页面,发现之类 另一一八个 id都变了,机会机会是新的Apache守护进程池池了,守护进程池池id是新的,hash key就变了,PHP只好重新连接MySQL,连接资源推入persistent list。机会15内刷新呢?Apache守护进程池池肯定不变,MySQL守护进程池号会变吗?答案得问MySQL了。首先之类 MySQL_thread_id是之类 东西?shell法律最好的最好的办法登录MySQL后执行命令'show processlist;',就看了之类 ?

?>

else

  Keep-Alive

  | Id  | User | Host      | db   | Command| Time| State| Info            |

  很简单,获取当前PHP执行者(Apache)的守护进程池池号,用浏览器浏览之类 页面,就看之类 ?对,有就看一串守护进程池池号数字,15秒内,连续刷新页面,看看守护进程池池号否有 变化?木有吧?现在把手拿开,交叉在胸前,度好时间,1秒,2秒,3,...15,16。好,过了15秒了,再去刷新页面,守护进程池池号有那末 变化?变了!又是一另一一八个 新的Apache守护进程池池了,为之类 15秒后就变成新的守护进程池池了?记得许多人在Apache里设置的KeepAliveTimeout吗?它的值而是我15秒。现在许多人应该大致清楚了,在web服务器默认打开KeepAlive的情形下,客户端第一次http成功请求后,Apache太少立刻断开socket,而是我老是监听来自之类 客户端的请求,监听多久?根据KeepAliveTimeout选项配置的时间决定,一旦超过之类 时间,Apache就会断开socket了,那末 下次同一客户端再次请求,Apache就会新开一另一一八个 守护进程池池来相应。一些一些许多人后后15内不停的刷新页面,就看的守护进程池池号需要一致的,表明是浏览器请求给了同一另一一八个 Apache守护进程池池。

  发现了有点痛 要的信息,之类 processlist列表而是我记录了正在跑的守护进程池,忽略Info列为show processlist那行,那行有了你当前shell登录MySQL的守护进程池。PHP连接MySQL的守护进程池而是我Id为349那行,机会读者当时人做测试,应该知道之类 Id=349在你的测试环境里是另外一另一一八个 值,许多人把之类 值和网页里输出的MySQL_thread_id($conn)做做比较,对!许多人是一样的。接下来最重要的是观察Command列和Time列,Command = Sleep,表明之类 ?表明许多人mysql_pconnect连接后就老是在sleep,Time字段就不知道们,之类 守护进程池Sleep了多久,那末 Sleep了多久之类 守护进程池太少 作废呢?那而是我wait_timeout机会interactive_timeout要做的工作了,许多人默认的值需要8小时,天啊,太少了,一些一些机会说web服务器关掉KeepAlive支持,那个之类 processlist很容易就被撑爆,就爆出那个Too many connections的错误了,max_connectiosns配置得再多也没用。为了观察之类 另一一八个 参数,许多人还可以在MySQL配置文件my.cnf里设置之类 另一一八个 值,找到[MySQLd]节点,在底下设置多两行

...

PHP的

}

?>

  好了,重启Apache,

一下,赶紧写行东西:

  2   echo "Apache守护进程池池号:". getmypid();

hashed_details_length = spprintf(&hashed_details, 0, "MySQL__%s_", user);

  Keep-Alive是之类 东西?它是http协议的一次责,你还可以 们复习一下那末 Keep-Alive的http请求,从客户在浏览器输入一另一一八个 有效url地址现在开始,浏览器就会利用socket向url对应的web服务器发送四根TCP请求,之类 请求成功一次就得需要来回握三次手太少 确定 ,成功后后,浏览器利用socket TCP连接资源向web服务器请求http协议,发送后后就等着web服务器把http返回头和body发送回来,发回来后浏览器关闭socket连接,因此做http返回头和body的解析

...

  总结

new_le.ptr = mysql;

echo "MySQL守护进程池号:". MySQL_thread_id($conn). "<br />";

  MySQL的wait_timeout和interactive_timeout

最新内容请见作者的GitHub页:http://qaseven.github.io/

  1 interactive_timeout = 60

}

/* we don't */

#2.机会未找到已有资源,就推入hash表,名字叫persistent_list,机会找到就直接使用

...

}

  配置后后,重启MySQL,shell登录MySQL,这后后show processlist还可以发现上还可以 当前守护进程池。因此运行那个涵盖mysql_pconnect的PHP页面,再回来MySQL端show processlist可发现,多了一另一一八个 Commond为Sleep的守护进程池,不停的show processlist(方向键上+enter键)观察Time列的变化2,5,10...14!,老是那个Sleep守护进程池程被kill掉了,咋回事,还没到60 秒呢,噢!忘了修改一下Apache keepalive的参数了,把KeepAliveTimeOut从15改成120(只为观察,才那末 改),重启Apache。刷新那个页面,好,现在开始不停的show processlist,2..5..10..14,15,..20...26....28,29!守护进程池被kill,这次是机会wait_timeout起了作用,浏览器那边停了60 秒,60 内机会浏览器刷新,那之类 Time又会从0现在开始计时。之类 连接不属于interactive connection(MySQL shell登录那种连接就属于interactive connection),一些一些采用了wait_timeout的值。机会mysql_pconnect的第一另一一八个 参数改改呢

服务器否有 支持Keep-Alive。

  说完Keep-Alive,该到MySQL家串串门了,说的是mysql_pconnect,缘何能绕开MySQL的设置。影响mysql_pconnect最重要的一另一一八个 参数而是我wait_timeout和interactive_timeout,它们是之类 东西?先撇一边,首先你还可以 们把底下的代码改动一下PHP代码

$conn = mysql_pconnect("localhost","root","123456") or die("Can not connect to MySQL");

mysql = (PHP_mysql_conn *) le->ptr;//直接使用对应的sql连接资源

  [sql] view plaincopy

  PHP缘何做

echo "Apache守护进程池池号". getmypid();

...

/* try to find if we already have this link in our persistent list */

if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {

  | 348 | root | localhost | NULL | Query  |    0| NULL | show processlist|

  3?>

持久化连接,美好的目标,却拥有糟糕的口碑,往往令人敬而远之。这到底是缘何么。近距离观察后发现,这家伙而是我容易啊,要看Apache的脸色,还得听MySQL指挥。

...

,最后呈现在浏览器上的而是我漂亮的页面了。这底下有之类 问题报告 呢?TCP连接需要三次握手,也而是我来回请求三次方能确定 一另一一八个 TCP请求否有 成功,因此TCP关闭呢?来回需要4次请求太少 完成!每次http请求就3次握手,4次拜拜,这来来回回的不嫌累啊,多少时间和资源都被浪费在socket连接关闭上了,还可以一次socket TCP连接发送多次http请求呢?于是Keep-Alive就应运而生,http/1.0里需要客户端当时人在请求头加入Connection:Keep-alive方能实现,在这里许多人只考虑http1.1了,只需要设置一下Apache,让它默认而是我Keep-Alive持久连接模式(Apache需要1.2+太少 支持Keep-Alive)。在httpd.conf里找到KeepAive配置项,果断设置为On,MaxKeepAliveRequests果断为0(一另一一八个 持久TCP最多允许的请求数,机会过小,很容易在TCP未过期的情形下,达到最大连接,那下次连接就又是新的TCP连接了,这里设置0表示不限制),因此对于mysql_pconnect最重要的选项KeepAliveTimeout设置为15(表示15秒)。

  刷新下页面,MySQL那边现在开始刷show processlist,这回Time > 60 而是我会被kill,>60 才被kill了,说明设置了MySQL_CLIENT_INTERACTIVE,就会被MySQL视为interactive connection,那末 这次PHP的MySQL连接在120秒内未刷新的情形下,多会儿作废将取决于MySQL的interactive_timeout的配置值。

{/* The link is in our list of persistent connections(连接已在hash表里)*/

$conn = mysql_pconnect('localhost','root','123456',MySQL_CLIENT_INTERACTIVE);

  mysql> show processlist;

  PHP的mysql_pconnect要达到功效,首先需要保证Apache是支持keep alive的,其次KeepAliveTimeOut应该设置多久呢,要根据自身站点的访问情形做调整,时间太短,keep alive没啥意义,时间太长,就很机会为一另一一八个 闲客户端连接牺牲一些一些服务器资源,毕竟hold住socket监听守护进程池池是要消耗cpu内存的。最后Apache的KeepAliveTimeOut配置得和MySQL的time out配置要有个平衡点,联系以上的观察,假设mysql_pconnect未带上第一另一一八个 参数,机会Apache的KeepAliveTimeOut设置的秒数比wait_timeout小,那真正对mysql_pconnect起作用的是Apache而需要MySQL的配置。这时机会MySQL的wait_timeout偏大,并发量大的情形下,很机会就一堆废弃的connection了,MySQL这边机会不及时回收,那就很机会Too many connections了。曾经机会KeepAliveTimeOut太少呢,又回到后后的问题报告 ,一些一些貌似Apache。KeepAliveTimeOu太少太少,但比MySQL。wait_timeout 稍大,机会相等是比较好的方案,曾经还可以保证keep alive过期后,废弃的MySQL连接还可以及时被回收。   

/* hash it up(推入hash表) */

  对于作为Apache模块运行的PHP来说,要实现MySQL持久化连接,首先得取决于Apache之类

  | 349 | root | localhost | NULL | Sleep  |    2|      | NULL            |

  +-----+------+-----------+------+--------+-----+------+-----------------+

  那末 ,PHP的MySQL连接资源是缘何被hold住的呢,这需要查看PHP的mysql_pconnect的函数代码,你还可以看下,为宜的做法而是我mysql_pconnect根据当前Apache守护进程池池号,生成hash key,找hash表内否有 对应的连接资源,那末 则推入hash表,有则直接使用。一些代码片段还可以说明(具体可查看PHP5.3.8源码ext/mysql/PHP_mysql.c文件690行PHP_mysql_do_connect函数)

//hashed_details而是我hash key

  +-----+------+-----------+------+--------+-----+------+-----------------+

  1<?php

...

...

echo "MySQL守护进程池号:".MySQL_thread_id($conn)."<br />";

user=php_get_current_user();//获取当前PHP执行者(Apache)的守护进程池池唯一标识号