什么是长连接?
其实长连接是相对于通常的短连接而说的,也就是长时间保持客户端与服务端的连接状态。
通常的短连接操作步骤是:
连接-》数据传输-》关闭连接;
而长连接通常就是:
连接-》数据传输-》保持连接-》数据传输-》保持连接-》…………-》关闭连接;
这就要求长连接在没有数据通信时,定时发送数据包,以维持连接状态,短连接在没有数据传输时直接关闭就行了
什么时候用长连接,短连接?
长连接主要用于在少数客户端与服务端的频繁通信,因为这时候如果用短连接频繁通信常会发生Socket出错,并且频繁创建Socket连接也是对资源的浪费。
但是对于服务端来说,长连接也会耗费一定的资源,需要专门的线程(unix下可以用进程管理)来负责维护连接状态。
总之,长连接和短连接的选择要视情况而定。
首先,如果使用了长连接而长期没有对数据库进行任何操作,那么在timeout值后,mysql server就会关闭此连接,而客户端在执行查询的时候就会得到一个类似于“MySQL server has gone away“这样的错误。
在使用mysql_real_connect连接数据库之后,再使用mysql_options( &mysql, MYSQL_OPT_RECONNECT, … ) 来设置为自动重连。这样当mysql连接丢失的时候,使用mysql_ping能够自动重连数据库。如果是在mysql 5.1.6之前,那么则应在每次执行完real_connect 之后执行mysql_options( &mysql, MYSQL_OPT_RECONNECT, … ) ,如果是mysql 5.1.6+,则在connect之前执行一次就够了。
下一篇:
第一种方法,当然是增加你的 wait-timeout值,这个参数是在my.cnf(在Windows下台下面是my.ini)中设置,我的数据库负荷稍微大一点,所以,我设置的值为10,(这个值的单位是秒,意思是当一个数据库连接在10秒钟内没有任何操作的话,就会强行关闭,我使用的不是永久链接(mysql_pconnect),用的是mysql_connect,关于这个wait-timeout的效果你可以在MySQL的进程列表中看到(show processlist) ),你可以把这个wait-timeout设置成更大,比如300秒,呵呵,一般来讲300秒足够用了,其实你也可以不用设置,MySQL默认是8个小时。情况由你的服务器和站点来定。
第二种方法:
这也是我个人认为最好的方法,即检查MySQL的链接状态,使其重新链接。
可能大家都知道有mysql_ping这么一个函数,在很多资料中都说这个mysql_ping的API会检查数据库是否链接,如果是断开的话会尝试重新连接,但在我的测试过程中发现事实并不是这样子的,是有条件的,必须要通过mysql_options这个C API传递相关参数,让MYSQL有断开自动链接的选项(MySQL默认为不自动连接),但我测试中发现PHP的MySQL的API中并不带这个函数,你重新编辑MySQL吧,呵呵。但mysql_ping这个函数还是终于能用得上的,只是要在其中有一个小小的操作技巧:
这是我的的数据库操作类中间的一个函数
function ping(){
if(!mysql_ping($this->link)){
mysql_close($this->link); //注意:一定要先执行数据库关闭,这是关键
$this->connect($this->t_dbhost,$this->t_dbuser,$this->t_dbpw,$this->t_dbname,$this->t_pconnect);
}
}
我需要调用这个函数的代码可能是这样子的
for($i=0;$i<10;i++){
$str=file_get_contents(’http://www.aol.com’);
}
$db->ping(); //经过前面的网页抓取后,或者会导致数据库连接关闭,检查并重新连接
$db->query(’select * from table’);
ping()这个函数先检测数据连接是否正常,如果被关闭,整个把当前脚本的MYSQL实例关闭,再重新连接。
经过这样处理后,可以非常有效的解决MySQL server has gone away这样的问题,而且不会对系统造成额外的开销。
对俩者的链接速度很好奇,就测试了一下...
php5,mysql5.
表里有3000条数据,
短连接查询前1000条,连接断开10次数据库,进行查询;
长连接查询后1000条,连接1次数据库,进行10次查询;
大部分测试,结果类似下边, 短连接耗时117毫秒, 长连接 13 毫秒.
<?php
require("db_conn.php");
$mysql_server_name="127.0.0.1"; //数据库服务器名称
$mysql_username="root"; // 连接数据库用户名
$mysql_password="root"; // 连接数据库密码
$mysql_database="osc_store"; // 数据库的名字
$search_count=10;
$search_number = 100;
//开始
$begin = microtime()*1000;
for($i=0;$i<$search_count;$i++){
$dbConn=mysql_connect($mysql_server_name, $mysql_username,$mysql_password);
mysql_select_db($mysql_database, $dbConn);
$queryStr = "select * from `products_description` order by products_id asc limit ".($i*$search_number)." ".$search_number;
$result = mysql_query($queryStr,$dbConn);
if(!result){
die(mysql_error());
}
$list = array();
while($row=mysql_fetch_array($result)){
$list[$row["id"]] = $row;
}
mysql_free_result($result);
mysql_close($dbConn);
}
$end = microtime()*1000;
echo "sort connection: ".$end." - ".$begin.": ".(($end-$begin))." millisecond<br/>";
unset($list);
//开始
$begin = microtime()*1000;
$dbConn=mysql_connect($mysql_server_name, $mysql_username,$mysql_password);
mysql_select_db($mysql_database, $dbConn);
for($i=0;$i<$search_count;$i++){
$queryStr = "select * from `products_description` order by products_id desc limit ".($i*$search_number)." ".$search_number;
$result = mysql_query($queryStr,$dbConn);
if(!result){
die(mysql_error());
}
$list = array();
while($row=mysql_fetch_array($result)){
$list[$row["id"]] = $row;
}
mysql_free_result($result);
}
mysql_close($dbConn);
$end = microtime()*1000;
echo "long connection: ".$end." - ".$begin.": ".(($end-$begin))." millisecond";
?>