通过PHP单例模式与长连接减少MySql连接数

dafenqi
2023-08-11 / 0 评论 / 16 阅读 / 正在检测是否收录...

通过PHP单例模式与长连接减少MySql连接数

此单例代码有问题,请参考下面的

在Mysql驱动的PHP网站中,MySql连接的一般都是利用脚本的结束来进行释放,在一些分层写的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
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

如何解决多次刷新情况下的大量连接呢,答案是用mysql长连接;

我们把上面的代码的

$connec=mysqli_connect("127.0.0.1", "root", "root"); //数据库地址和密码等

改为

$connec=mysqli_connect("p:127.0.0.1", "root", "root"); //数据库地址和密码等

注意:上面的代码在IP地址前加了一个“p:”前缀,代表使用的是mysql长连接,修改完成后,我们再来多次刷新页面。

ll5ypzgj.png

如上图,只有2个连接了。解决成功。

当然,除了用mysql的长连接外,还可以修改linux 内核参数的连接重用参数,也可以达到目的。

用mysql长连接能大大提升性能,所以请务必使用mysql长连接。

0

Deprecated: strtolower(): Passing null to parameter #1 ($string) of type string is deprecated in /www/wwwroot/testblog.58heshihu.com/var/Widget/Archive.php on line 1032

评论 (0)

取消