Yii2数据库链接

咱们公司使用的php框架是Yii2,最近由于线上出现了数据库链接被打满,致使线上业务出现异常的状况,就专门研究了下Yii的数据库连接问题。php

一、Yii2怎么连接数据库的

咱们项目中使用的是主从分离的mysql数据库。使用的是配置中的components的方式,其中每一个数据库的配置都是一个component。这样就将数据库的配置注册到Yii::$app中,能够在model中直接在getDb中获取数据库的配置信息,以下mysql

$config = [
    "components" => [
        "exam" => [
            "class" => "yii\db\Connection",  //使用的数据库链接类
            "charset" => "utf8", //使用的链接编码方式
            "enableSchemaCache" => true, //启用数据库schema的缓存
            "schemaCacheDuration" => 3600, //缓存时间1小时
            "username" => "", //用户名
            "dsn" => "",
            "masterConfig" => [...], //主库配置
            "masters" => [], //主库dsn列表
            "slaveConfig" => [...], //从库配置,
            "slaves" => [], //从库dsn配置
        ]
    ]
];

这样咱们就配置了一个exam的数据库,而在实际的model中时,能够在这个数据库的基类中主从使用的数据库配置:nginx

class Exam extends \yii\db\ActiveRecord {
    public static function getDb() {
        return  \Yii::$app->exam;
    }
}

数据库中每一个表都有一个本身的model类,继承这个基类,这样在数据库表中执行的数据库操做就会自动的使用这个数据库的配置。
同时,在进行数据库操做时,框架会自动的进行数据库的读写分离,插入、更新和删除的操做会使用主库,查询操做会自动使用从库。当须要在主库查询时,也能够使用getDb()->useMaster()来从主库进行查询。
在获取从库链接的时候,若是获取从库链接失败,而且容许获取主库(默认是容许自动调整的),就会自动获取主库的链接。sql

二、Yii2何时创建链接

2.1 数据库何时创建链接呢?有两种可能:

一、在请求到来以后,Yii2进行初始化的时候创建链接。
这个是不可能的,咱们的项目配置了几十个数据库,而每次请求来了的时候不可能为每一个数据库创建一个链接,这是一种浪费:一方面一个请求不可能用到全部的数据库;另外一方面创建了数据库链接又不使用,对数据库的资源也是一种浪费。
二、在执行数据库model方法的时候
这样只有在使用到相应数据库查询的时候,才会创建该数据库的链接,这样能够尽量的优化数据库资源的使用。
同时在一个请求中,若是已经创建了一个数据库的链接,接下来执行相似操做时就会复用这个数据库的链接,减小数据库连接的创建。数据库

2.2 创建数据库链接的方法

在创建数据库链接的时候,最底层调用的方法时Yii2\db\Conection类中的openFromPool方法,从方法名看,是从池子中打开一个链接,其实这里是从以前配置的数据库列表中随机获取一个链接:缓存

protected function openFromPool(array $pool, array $sharedConfig) {
        if (empty($pool)) {
            return null;
        }
        if (!isset($sharedConfig['class'])) {
            $sharedConfig['class'] = get_class($this);
        }
        $cache = is_string($this->serverStatusCache) ? Yii::$app->get($this->serverStatusCache, false) : $this->serverStatusCache;
        //这里会先将从库的地址列表打乱,而后循环这个配置列表,逐一创建链接,直到创建链接成功。若是都创建失败会返回null
        shuffle($pool);
       foreach ($pool as $config) {
           ...
           try {
                //这里就是实际的创建链接的方法
                $db->open();
                return $db;
           }
       }
    return null;

这里有一个要注意的点,在调用openFromPool创建链接的时候,底层使用的实际方法是open。这里要注意,在获取从库时,是使用生成的$db对象来创建的,而获取主库时直接使用的$this,因此在open方法中会判断是否有$this->masters,只有在主库时才会有值,才会创建主库的链接。
这里最开始觉得时每次都创建主库链接,直到后来看到$db才发现不是最开始的Connection对象了。php框架

三、Yii2何时销毁连接

上面说了,咱们是在执行数据库表对应的model文件的方法时,才会创建数据库链接,而这个数据库的链接会被放到db对象中,其中从库会放到_slave里面,主库的链接放到pdo里面。这样在获取的时候,若是有值,就会直接使用。
具体的销毁是在php请求完毕以后,当php把返回值发送给nginx以后,php释放相关的对象值时。
最后,使用Yii2时仍是推荐使用主从数据库配置的,这样能够减小主服务器的压力,避免形成主服务器的问题,同时,若是查询压力太大的时候,能够很方便的扩展从库,增长系统的抗压能力。服务器

相关文章
相关标签/搜索