PHP API中,MYSQL与MYSQLI的持久连接区别

很久很久以前,我也是因为工作上的bug,研究了php mysql client的连接驱动mysqlnd 与libmysql之间的区别php与mysql通讯那点事,这次又遇到一件跟他们有联系的事情,mysqli与mysql持久链接的区别。写出这篇文章,用了好一个多月,其一是我太懒了,其二是工作也比较忙。最近才能腾出时间,来做这些事情。每次做总结,都要认真阅读源码,理解含义,测试验证,来确认这些细节。而每一个步骤都需要花费很长的时间,而且,还不能被打断。一旦被打断了,都需要很长时间去温习上下文。也故意强迫自己写这篇总结,改改自己的惰性。

在我和我的小伙伴们如火如荼的开发、测试时发生了“mysql server too many connections”的错误,稍微排查了一下,发现是php后台进程建立了大量的链接,而没有关闭。服务器环境大约如下php5.3.x 、mysqli API、mysqlnd 驱动。代码情况是这样:


//后台进程A/*配置信息'mysql'=>array(     'driver'=>'mysqli',//   'driver'=>'pdo',//   'driver'=>'mysql',     'host'=>'192.168.111.111',     'user'=>'root',     'port'=>3306,     'dbname'=>'dbname',     'socket'=>'',     'pass'=>'pass',     'persist'=>true,    //下面有提到哦,这是持久链接的配置    ),*/$config=Yaf_Registry::get('config');$driver = Afx_Db_Factory::DbDriver($config['mysql']['driver']);     //mysql  mysqli$driver::debug($config['debug']);     //注意这里$driver->setConfig($config['mysql']);     //注意这里Afx_Module::Instance()->setAdapter($driver);     //注意这里,哪里不舒服,就注意看哪里。$queue=Afx_Queue::Instance();$combat = new CombatEngine();$Role = new Role(1,true);$idle_max=isset($config['idle_max'])?$config['idle_max']:1000;while(true){    $data = $queue->pop(MTypes::ECTYPE_COMBAT_QUEUE, 1);    if(!$data){        usleep(50000);    //休眠0.05秒         ++$idle_count;        if($idle_count>=$idle_max)        {            $idle_count=0;             Afx_Db_Factory::ping();        }        continue;    }    $idle_count=0;    $Role->setId($data['attacker']['role_id']);    $Property   = $Role->getModule('Property');    $Mounts     = $Role->getModule('Mounts');    //............    unset($Property, $Mounts/*.....*/);}

从这个后台进程代码中,可以看出“$Property”变量以及“$Mounts”变量频繁被创建,销毁。而ROLE对象的getModule方法是这样写的


//ROLE对象的getModule方法class Role extends Afx_Module_Abstract{    public function getModule ($member_class)    {        $property_name = '__m' . ucfirst($member_class);        if (! isset($this->$property_name))        {            $this->$property_name = new $member_class($this);        }        return $this->$property_name;    }}//Property 类class Property extends Afx_Module_Abstract{    public function __construct ($mRole)    {        $this->__mRole = $mRole;    }}

可以看出getModule方法只是模拟单例,new了一个新对象返回,而他们都继承了Afx_Module_Abstract类。Afx_Module_Abstract类大约代码如下:


abstract class Afx_Module_Abstract{    public function setAdapter ($_adapter)    {        $this->_adapter = $_adapter;    }}

类Afx_Module_Abstract中关键代码如上,跟DB相关的,就setAdapter一个方法,回到“后台进程A”,setAdapter方法是将Afx_Db_Factory::DbDriver($config['mysql']['driver'])的返回,作为参数传了进来。继续看下Afx_Db_Factory类的代码


class Afx_Db_Factory{    const DB_MYSQL = 'mysql';    const DB_MYSQLI = 'mysqli';    const DB_PDO = 'pdo';    public static function DbDriver ($type = self::DB_MYSQLI)    {        switch ($type)        {            case self::DB_MYSQL:                $driver = Afx_Db_Mysql_Adapter::Instance();                break;            case self::DB_MYSQLI:                $driver = Afx_Db_Mysqli_Adapter::Instance();    //走到这里了                break;            case self::DB_PDO:                $driver = Afx_Db_Pdo_Adapter::Instance();                break;            default:                break;        }        return $driver;    }}

郑重声明:本文版权包含图片归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们(delete@yzlfxy.com)修改或删除,多谢。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

留言与评论(共有 0 条评论)
昵称:
匿名发表
   
验证码: