php 连接MYSQL 两个同时连接为什么只有一个连接微信支付成功回调 php,必须删掉一个,另外一个才查询生效出结果,下附代码

&?php$mysqli = new mysqli("localhost", "my_user", "my_password", "world");/* check connection */if ($mysqli-&connect_errno) {
printf("Connect failed: %s\n", $mysqli-&connect_error);
exit();}/* Create table doesn't return a resultset */if ($mysqli-&query("CREATE TEMPORARY TABLE myCity LIKE City") === TRUE) {
printf("Table myCity successfully created.\n");}/* Select queries return a resultset */if ($result = $mysqli-&query("SELECT Name FROM City LIMIT 10")) {
printf("Select returned %d rows.\n", $result-&num_rows);
/* free result set */
$result-&close();}/* If we have to retrieve large amount of data we use MYSQLI_USE_RESULT */if ($result = $mysqli-&query("SELECT * FROM City", MYSQLI_USE_RESULT)) {
/* Note, that we can't execute any functions which interact with the
server until result set was closed. All calls will return an
'out of sync' error */
if (!$mysqli-&query("SET @a:='this will not work'")) {
printf("Error: %s\n", $mysqli-&error);
$result-&close();}$mysqli-&close();?&
如上代码:我每次查询需不需要用$mysqli-&close();来关闭数据库连接呢?如果关闭,第二次用到查询会不会因重新连接数据库而造成性能上的影响。如果不关,会不会造成服务器的资源浪费?
该问题被发起重新开启投票
投票剩余时间:
之前被关闭原因:
该问题被发起删除投票
投票剩余时间:
距离悬赏到期还有:
参与关闭投票者:
关闭原因:
该问题已经被锁定
锁定原因:()
保护原因:避免来自新用户不合宜或无意义的致谢、跟帖答案。
该问题已成功删除,仅对您可见,其他人不能够查看。
你其实可以写一个 db类
在类里 写一个__destruct方法
在里面关闭会比较好点 我想对于php类的概念 你应该知道吧;
关闭是为了释放资源,就像楼上所说的,你需要写一个__destruct() 析构方法,系统会自动调用的,
用__destruct方法没错的,一般的CMS系统中,会把数据库操作封装为一个类,在系统开始会先建立一个全局的DB对象,然后一个回调过程完成之后DB就会自动调用__destruct()来释放连接,这样一次请求中就只会有一个数据库会话在运作。
数据库连接与释放都比较耗资源,要对数据库会话合理利用。
mysqli 和 mysql 操作类都是类似的,基本上只需要换下对应的库函数,参数调整下即可
德问是一个专业的编程问答社区,请
后再提交答案
关注该问题的人
共被浏览 (5366) 次PHP数据库长连接mysql
我的图书馆
PHP数据库长连接mysql
PHP的MySQL持久化连接,美好的目标,却拥有糟糕的口碑,往往令人敬而远之。这到底是为啥么。近距离观察后发现,这家伙也不容易啊,要看Apache的脸色,还得听MySQL指挥。
对于作为Apache模块运行的PHP来说,要实现MySQL持久化连接,首先得取决于Apache这个web服务器是否支持Keep-Alive。
Keep-Alive
Keep-Alive是什么东西?它是http协议的一部分,让我们复习一下没有Keep-Alive的http请求,从客户在浏览器输入一个有效url地址开始,浏览器就会利用socket向url对应的web服务器发送一条TCP请求,这个请求成功一次就得需要来回握三次手才能确定,成功以后,浏览器利用socket TCP连接资源向web服务器请求http协议,发送以后就等着web服务器把http返回头和body发送回来,发回来后浏览器关闭socket连接,然后做http返回头和body的解析工作,最后呈现在浏览器上的就是漂亮的页面了。这里面有什么问题呢?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秒)。
好了,重启Apache,测试一下,赶紧写行东西:
1&?php2&&&&echo "Apache进程号:". getmypid();3?&
很简单,获取当前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进程。
浏览器是怎么知道不需要重新进行TCP连接就可以直接发送http请求呢?因为http返回头里就会带上Connection:keep-alive,Keep-alive:15两行,意思就是让客户端浏览器明白,这次socket连接我这边还没关闭呢,你可以在15内继续使用这个连接,并发送http请求,于是乎浏览器就知道应该怎么做了。
那么,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函数)
01#1.生成hash key02user=php_get_current_user();//获取当前PHP执行者(Apache)的进程唯一标识号03//hashed_details就是hash key04hashed_details_length = spprintf(&hashed_details, 0, "MySQL__%s_", user);05#2.如果未找到已有资源,就推入hash表,名字叫persistent_list,如果找到就直接使用06/* try to find if we already have this link in our persistent list */07if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) {& 08&&&&/* we don't */09&&&&...10&&&&...11&&&&/* hash it up(推入hash表) */12&&&&Z_TYPE(new_le) = le_13&&&&new_le.ptr =14&&&&if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {15&&&&&&&&...16&&&&&&&&...&&&&& 17&&&&&&&&}18&&&&}19&&&&else20&&&&{/* The link is in our list of persistent connections(连接已在hash表里)*/21&&&&&&&&...22&&&&&&&&...23&&&&&&&&mysql = (PHP_mysql_conn *) le-&//直接使用对应的sql连接资源24&&&&&&&&...25&&&&&&&&...26&&&&}
zend_hash_find比较容易看明白,原型是zend_hash_find(hash表,key名,key长,value);如果找到,value就有值了。
MySQL的wait_timeout和interactive_timeout
说完Keep-Alive,该到MySQL家串串门了,说的是mysql_pconnect,怎么能绕开MySQL的设置。影响mysql_pconnect最重要的两个参数就是wait_timeout和interactive_timeout,它们是什么东西?先撇一边,首先让我们把上面的代码改动一下PHP代码
12&&&&$conn = mysql_pconnect("localhost","root","123456") or die("Can not connect to MySQL");3&&&&echo "MySQL线程号:". MySQL_thread_id($conn). "";4&&&&echo "Apache进程号". getmypid();5?&
以上的代码没啥好解释的,让我们用浏览器浏览这个页面,看到什么?看到两个显眼的数字。一个是MySQL线程号,一个是Apache进程号,好了,15秒后再刷新这个页面,发现这两个id都变了,因为已经是新的Apache进程了,进程id是新的,hash key就变了,PHP只好重新连接MySQL,连接资源推入persistent list。如果15内刷新呢?Apache进程肯定不变,MySQL线程号会变吗?答案得问MySQL了。首先这个MySQL_thread_id是什么东西?shell方式登录MySQL后执行命令'',看到了什么?
1mysql&2+-----+------+-----------+------+--------+-----+------+-----------------+3| Id& | User | Host&&&&& | db&& | Command| Time| State| Info&&&&&&&&&&& |4+-----+------+-----------+------+--------+-----+------+-----------------+5| 348 | root | localhost | NULL | Query& |&&& 0| NULL | show processlist|6| 349 | root | localhost | NULL | Sleep& |&&& 2|&&&&& | NULL&&&&&&&&&&& |7+-----+------+-----------+------+--------+-----+------+-----------------+
发现了很重要的信息,这个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]节点,在里面设置多两行
1interactive_timeout = 602wait_timeout&&&&&&& = 30
配置完后,重启MySQL,shell登录MySQL,这时候show processlist可以发现只有当前线程。然后运行那个带有mysql_pconnect的PHP页面,再回来MySQL端show processlist可发现,多了一个Commond为Sleep的线程,不停的show processlist(方向键上+enter键)观察Time列的变化2,5,10...14!,突然那个Sleep线程程被kill掉了,咋回事,还没到30秒呢,噢!忘了修改一下Apache keepalive的参数了,把KeepAliveTimeOut从15改成120(只为观察,才这么改),重启Apache。刷新那个页面,好,开始不停的show processlist,2..5..10..14,15,..20...26....28,29!线程被kill,这次是因为wait_timeout起了作用,浏览器那边停了30秒,30内如果浏览器刷新,那这个Time又会从0开始计时。这种连接不属于interactive connection(MySQL shell登录那种连接就属于interactive connection),所以采用了wait_timeout的值。如果mysql_pconnect的第4个参数改改呢
12$conn = mysql_pconnect('localhost','root','123456',MySQL_CLIENT_INTERACTIVE);3echo "MySQL线程号:".MySQL_thread_id($conn)."";4echo "Apache进程号:".getmypid();5?&
刷新下页面,MySQL那边开始刷show processlist,这回Time & 30也不会被kill,&60才被kill了,说明设置了MySQL_CLIENT_INTERACTIVE,就会被MySQL视为interactive connection,那么这次PHP的MySQL连接在120秒内未刷新的情况下,何时作废将取决于MySQL的interactive_timeout的配置值。
PHP的mysql_pconnect要达到功效,首先必须保证Apache是支持keep alive的,其次KeepAliveTimeOut应该设置多久呢,要根据自身站点的访问情况做调整,时间太短,keep alive没啥意义,时间太长,就很可能为一个闲客户端连接牺牲很多服务器资源,毕竟hold住socket监听进程是要消耗cpu内存的。最后Apache的KeepAliveTimeOut配置得和MySQL的time out配置要有个平衡点,联系以上的观察,假设mysql_pconnect未带上第4个参数,如果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连接可以及时被回收。
TA的最新馆藏
喜欢该文的人也喜欢php连接MySQL的两种方式对比 - ThinkPHP框架
这篇文章主要介绍了php连接MySQL的两种方式对比,一种是原生的链接方式另外一种是PDO方式,附上示例,推荐给大家,有需要的小伙伴可以参考下
记录一下PHP连接MySQL的两种方式。
先mock一下数据,可以执行一下sql。
$host&=&'localhost';
$database&=&'test';
$username&=&'root';
$password&=&'root';
$selectName&=&'harry';//要查找的用户名,一般是用户输入的信息
$connection&=&mysql_connect($host,&$username,&$password);//连接到数据库
mysql_query(&set&names&'utf8'&);//编码转化
if&(!$connection)&{
&&die(&could&not&connect&to&the&database.\n&&.&mysql_error());//诊断连接错误
$selectedDb&=&mysql_select_db($database);//选择数据库
if&(!$selectedDb)&{
&&die(&could&not&to&the&database\n&&.&mysql_error());
$selectName&=&mysql_real_escape_string($selectName);//防止SQL注入
$query&=&&select&*&from&user&where&name&=&'$selectName'&;//构建查询语句
$result&=&mysql_query($query);//执行查询
if&(!$result)&{
&&die(&could&not&to&the&database\n&&.&mysql_error());
while&($row&=&mysql_fetch_row($result))&{
&&//取出结果并显示
&&$name&=&$row[0];
&&$age&=&$row[1];
&&echo&&Name:&$name&&;
&&echo&&Age:&$age&&;
&&echo&&\n&;
其运行结构如下:
Name:&harry&Age:&20&
&Name:&tony&Age:&23&
第二种是使用PDO的方式去连接数据库,代码如下:
$host&=&'localhost';
$database&=&'test';
$username&=&'root';
$password&=&'root';
$selectName&=&'harry';//要查找的用户名,一般是用户输入的信息
$pdo&=&new&PDO(&mysql:host=$dbname=$database&,&$username,&$password);//创建一个pdo对象
$pdo-&exec(&set&names&'utf8'&);
$sql&=&&select&*&from&user&where&name&=&?&;
$stmt&=&$pdo-&prepare($sql);
$rs&=&$stmt-&execute(array($selectName));
if&($rs)&{
&&//&PDO::FETCH_ASSOC&关联数组形式
&&//&PDO::FETCH_NUM&数字索引数组形式
&&while&($row&=&$stmt-&fetch(PDO::FETCH_ASSOC))&{
&&&&$name&=&$row['name'];
&&&&$age&=&$row['age'];
&&&&echo&&Name:&$name&&;
&&&&echo&&Age:&$age&&;
&&&&echo&&\n&;
$pdo&=&//关闭连接
其结果与第一种相同。
以上所述就是本文的全部内容了,希望能够对大家熟练掌握mysql有所帮助。
积分:3984
ThinkPHP 是一个免费开源的,快速、简单的面向对象的 轻量级PHP开发框架 ,创立于2006年初,遵循Apache2开源协议发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。并且拥有众多的原创功能和特性,在社区团队的积极参与下,在易用性、扩展性和性能方面不断优化和改进,已经成长为国内最领先和最具影响力的WEB应用开发框架,众多的典型案例确保可以稳定用于商业以及门户级的开发。他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)一个PHP程序同时连接多个mysql数据库出现的小问题
最近在处理一个程序中遇到一个小问题,当时觉得很奇怪,后来在同事的协助下找了一些资料发现原来是mysql_connect这个函数造成的
是这样的 在一个程序中 同时对多个进行连接,程序实际设计多个数据库的意图是为了将数据库分离,减轻数据库服务器的压力,但是我在调试的过程中
都是在本地一个服务器中进行的 建立的了类似于如下的代码:
//前面定义dbhost dbuser dbpwd 等 变量
$conn1 = mysql_connect($dbhost,$dbuser,$dbpwd);
mysql_select_db(”database1&P,$conn1);
$conn2 = mysql_connect($dbhost,$dbuser,$dbpwd);
mysql_select_db(”database2&P,$conn2);
$conn3 = mysql_connect($dbhost,$dbuser,$dbpwd);
mysql_select_db(”database3&P,$conn3);
然后执行一个最简单的 从database1中的table1中查询出所有资料
mysql_query(”select * from table1 where 1&P,$conn1); //注意
这里指定了通过conn1的连接来进行操作
程序返回了错误
信息是 “table database3.table1 not exists ” 奇怪明明指定了conn1的
却为什么使用了conn3
再看php手册 中mysql_query的用法 :请大家注意加下划线的一行
resource&mysql_query&(
string query [, resource link_identifier] )
mysql_query()&向与指定的连接标识符关联的服务器中的当前活动数据库发送一条查询。如果没有指定&link_identifier,则使用上一个打开的连接。如果没有打开的连接,本函数会尝试无参数调用&mysql_connect()&函数来建立一个连接并使用之。查询结果会被缓存。
根据函数说明 我的用法并没有错! 明明已经加了 link_identifier 怎么还是使用了上一个打开的连接 ?
后来通过找了一些资料 再看手册 的mysql_connect函数 :
resource&mysql_connect&(
[string server [, string username [, string password
new_link&[, int client_flags]]]]] )
如果成功则返回一个 MySQL 连接标识,失败则返回&FALSE
我们一般都是用到password那个参数为止, bool
new_link这个我们很少用。上面因为使用了相同的用户名和密码
,虽然在我们看来建立的是3个链接,但是在mysql认为这是一个链接,通过查看mysql的实时状态也证实了只是一个链接,也就是conn2
conn3根本只是conn1的一个影射,影射完以后进行了一个更改数据库的操作!
最终这个链接定位到了database3上面!!
正确的代码写法如下:
$conn1 = mysql_connect("$dbhost",
"$dbuser","$dbpassword");
mysql_select_db(
"a",$conn1);
$conn2 = mysql_connect("$dbhost",
"$dbuser","$dbpassword",true);
mysql_select_db("b",$conn2);
看看mysql_connect该函数的第四个参数new_link,mysql_connect()默认new_link为false在一个脚本里用同样的参数调用N次的话,
它不会重新打开新的连接,而是直接返回上一次打开的连接资源句柄!
如果new_link值为true,它会重新打开一个新的连接并且返回新的连接资源句柄。
补充一下这个前提条件两个数据库要在同一服务器上,不在同一个服务器上的话可以不用。也就是说,同一个IP时需要指定true才会开新连接,
如果是不同IP, 默认就会打开新连接. 为通用起见, 第二个mysql_connect最好还是加上true.
这是mysql驱动做的处理, 参见手册。
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 微信支付成功回调 php 的文章

 

随机推荐