Loading... # [通过PHP单例模式与长连接减少MySql连接数](https://blog.p2hp.com/archives/6131) **此单例代码有问题,请参考下面的** 在Mysql驱动的PHP网站中,MySql连接的一般都是利用脚本的结束来进行释放,在一些分层写的php网站中,若一个页面含有多个数据访问类,由于每个数据访问类都会有数据库的连接,导致这一个页面在脚本结束前会有多个数据库连接,在一些大型的页面连接可能多至数十上百,为此需要进行必要的控制,对于解释性的PHP语言,脚本是顺序执行的,也就是说数据库连接的利用同时只有一个,根据这个特点,可以用单例模式来进行改造。 ```php <?php class ConnecToDB { private static $instance; private function _constuct() { } //私有构造函数,防止外界构造新对象, public static function GetConnec() { if (!self::$instance instanceof self) { self::$instance =new self;//若当前对象实例不存在 } $temp=self::$instance; //获取当前单例 return $temp::Con() ; //调用对象私有方法连接 数据库 } //连接到数据库 private static function Con() { try { $connec=mysqli_connect("127.0.0.1", "root", "root"); //数据库地址和密码等 mysqli_select_db($connec, "dbname");//选择数据库 } catch (Exception $e) { echo $e->getMessage().'<br/>'; } return $connec; } } $db=new ConnecToDB(); $db->GetConnec(); ``` **这是正确的单例代码** ```php <?php class Config1 {} class Config { /* * 必须先声明一个静态私有属性:用来保存当前类的实例 * 1. 为什么必须是静态的?因为静态成员属于类,并被类所有实例所共享 * 2. 为什么必须是私有的?不允许外部直接访问,仅允许通过类方法控制方法 * 3. 为什么要有初始值null,因为类内部访问接口需要检测实例的状态,判断是否需要实例化 */ private static $instance = null; //保存用户的自定义配置参数 private $setting = []; //构造器私有化:禁止从类外部实例化 private function __construct(){} //克隆方法私有化:禁止从外部克隆对象 private function __clone(){} //因为用静态属性返回类实例,而只能在静态方法使用静态属性 //所以必须创建一个静态方法来生成当前类的唯一实例 public static function getInstance() { //检测当前类属性$instance是否已经保存了当前类的实例 if (self::$instance == null) { //如果没有,则创建当前类的实例 //self::$instance = new self(); self::$instance= new mysqli(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME); self::$instance->set_charset('utf8'); } //如果已经有了当前类实例,就直接返回,不要重复创建类实例 return self::$instance; } //设置配置项 public function set($index, $value) { $this->setting[$index] = $value; } //读取配置项 public function get($index) { return $this->setting[$index]; } } //实例化Config类 $obj1 = Config::getInstance(); $obj2 = Config::getInstance(); var_dump($obj1,$obj2); $obj1->set('host','localhost'); echo $obj1->get('host'); ``` 当然这个代码中,数据库的账号、密码等连接信息都是硬编码,可以通过改造GetConnec()函数注入相应的信息。 通过这段脚本,就可以控制一个页面只有一次数据库连接。这就会减少mysql的连接数。但是虽然减少了单次请求的连接数,但是如果这个页面进行多次刷新的话,还是会生产大量mysql连接,降低性能,如图,页面进行多次刷新后,mysql连接数,出现很多: ![ll5yq87g.png](http://flt-pan.58heshihu.com/blog/typecho/ll5yq87g.png) 如何解决多次刷新情况下的大量连接呢,答案是用mysql长连接; 我们把上面的代码的 ```php $connec=mysqli_connect("127.0.0.1", "root", "root"); //数据库地址和密码等 改为 $connec=mysqli_connect("p:127.0.0.1", "root", "root"); //数据库地址和密码等 ``` 注意:上面的代码在IP地址前加了一个“p:”前缀,代表使用的是mysql长连接,修改完成后,我们再来多次刷新页面。 ![ll5ypzgj.png](http://flt-pan.58heshihu.com/blog/typecho/ll5ypzgj.png) 如上图,只有2个连接了。解决成功。 当然,除了用mysql的长连接外,还可以修改linux 内核参数的连接重用参数,也可以达到目的。 用mysql长连接能大大提升性能,所以请务必使用mysql长连接。 最后修改:2023 年 08 月 11 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏